@iyulab/u-board-designer 0.0.0-stage → 0.2.0

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 (82) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +127 -2
  3. package/dist/lib/authoring/AnchorFields.d.ts +12 -0
  4. package/dist/lib/authoring/AnchorFields.js +64 -0
  5. package/dist/lib/authoring/BackgroundField.d.ts +13 -0
  6. package/dist/lib/authoring/BackgroundField.js +38 -0
  7. package/dist/lib/authoring/BoardAuthoring.d.ts +37 -0
  8. package/dist/lib/authoring/BoardAuthoring.js +288 -0
  9. package/dist/lib/authoring/BoardElementsPanel.d.ts +14 -0
  10. package/dist/lib/authoring/BoardElementsPanel.js +49 -0
  11. package/dist/lib/authoring/BoardPanel.d.ts +40 -0
  12. package/dist/lib/authoring/BoardPanel.js +22 -0
  13. package/dist/lib/authoring/CanvasAuthoring.d.ts +13 -0
  14. package/dist/lib/authoring/CanvasAuthoring.js +161 -0
  15. package/dist/lib/authoring/DataPanel.d.ts +29 -0
  16. package/dist/lib/authoring/DataPanel.js +98 -0
  17. package/dist/lib/authoring/GridAuthoring.d.ts +13 -0
  18. package/dist/lib/authoring/GridAuthoring.js +135 -0
  19. package/dist/lib/authoring/GridItemPanel.d.ts +22 -0
  20. package/dist/lib/authoring/GridItemPanel.js +21 -0
  21. package/dist/lib/authoring/LinkPanel.d.ts +19 -0
  22. package/dist/lib/authoring/LinkPanel.js +24 -0
  23. package/dist/lib/authoring/MappingEditor.d.ts +23 -0
  24. package/dist/lib/authoring/MappingEditor.js +83 -0
  25. package/dist/lib/authoring/PartPanel.d.ts +24 -0
  26. package/dist/lib/authoring/PartPanel.js +78 -0
  27. package/dist/lib/authoring/ShapePanel.d.ts +20 -0
  28. package/dist/lib/authoring/ShapePanel.js +54 -0
  29. package/dist/lib/authoring/StatesEditor.d.ts +18 -0
  30. package/dist/lib/authoring/StatesEditor.js +79 -0
  31. package/dist/lib/authoring/StatusesPanel.d.ts +14 -0
  32. package/dist/lib/authoring/StatusesPanel.js +32 -0
  33. package/dist/lib/authoring/TriggersEditor.d.ts +30 -0
  34. package/dist/lib/authoring/TriggersEditor.js +137 -0
  35. package/dist/lib/authoring/ValueMapFields.d.ts +64 -0
  36. package/dist/lib/authoring/ValueMapFields.js +68 -0
  37. package/dist/lib/authoring/WidgetPropsForm.d.ts +27 -0
  38. package/dist/lib/authoring/WidgetPropsForm.js +56 -0
  39. package/dist/lib/authoring/background-image.d.ts +25 -0
  40. package/dist/lib/authoring/background-image.js +63 -0
  41. package/dist/lib/authoring/board-layout.d.ts +64 -0
  42. package/dist/lib/authoring/board-layout.js +326 -0
  43. package/dist/lib/authoring/board-triggers.d.ts +5 -0
  44. package/dist/lib/authoring/board-triggers.js +55 -0
  45. package/dist/lib/authoring/document-history.d.ts +23 -0
  46. package/dist/lib/authoring/document-history.js +37 -0
  47. package/dist/lib/authoring/editor-parts.d.ts +46 -0
  48. package/dist/lib/authoring/editor-parts.js +6 -0
  49. package/dist/lib/authoring/field-style.d.ts +3 -0
  50. package/dist/lib/authoring/field-style.js +2 -0
  51. package/dist/lib/authoring/part-names.d.ts +6 -0
  52. package/dist/lib/authoring/part-names.js +9 -0
  53. package/dist/lib/authoring/scene-mapping.d.ts +22 -0
  54. package/dist/lib/authoring/scene-mapping.js +124 -0
  55. package/dist/lib/authoring/use-edit-keys.d.ts +13 -0
  56. package/dist/lib/authoring/use-edit-keys.js +57 -0
  57. package/dist/lib/authoring/widget-catalog.d.ts +4 -0
  58. package/dist/lib/authoring/widget-catalog.js +9 -0
  59. package/dist/lib/authoring/widget-fields.d.ts +45 -0
  60. package/dist/lib/authoring/widget-fields.js +129 -0
  61. package/dist/lib/board/check.d.ts +27 -0
  62. package/dist/lib/board/check.js +48 -0
  63. package/dist/lib/board/rulebook.d.ts +7 -0
  64. package/dist/lib/board/rulebook.js +148 -0
  65. package/dist/lib/check-entry.d.ts +3 -0
  66. package/dist/lib/check-entry.js +4 -0
  67. package/dist/lib/editing/grid-editing.d.ts +19 -0
  68. package/dist/lib/editing/grid-editing.js +68 -0
  69. package/dist/lib/editing/part-removal.d.ts +4 -0
  70. package/dist/lib/editing/part-removal.js +11 -0
  71. package/dist/lib/editing/trigger-editing.d.ts +16 -0
  72. package/dist/lib/editing/trigger-editing.js +36 -0
  73. package/dist/lib/index.d.ts +7 -0
  74. package/dist/lib/index.js +5 -0
  75. package/dist/lib/labels-ko.d.ts +4 -0
  76. package/dist/lib/labels-ko.js +270 -0
  77. package/dist/lib/labels.d.ts +368 -0
  78. package/dist/lib/labels.js +273 -0
  79. package/dist/lib/use-labels.d.ts +7 -0
  80. package/dist/lib/use-labels.js +12 -0
  81. package/package.json +75 -4
  82. package/styles.css +277 -0
@@ -0,0 +1,19 @@
1
+ import { type CanvasView, type GridCanvasItem, type GridLayout, type GridView, type GridWidgetItem } from '@iyulab/u-board/picture';
2
+ /** What can change on a grid item: its room, and its widget and states or its canvas — whichever it holds. */
3
+ export type GridItemChange = Partial<GridLayout & Pick<GridWidgetItem, 'widget' | 'states'> & Pick<GridCanvasItem, 'canvas'>>;
4
+ /** The item with `id` changed by `change` — a field set to `undefined` is left out, so the document says only what
5
+ * differs from the default. */
6
+ export declare function updateGridItem(doc: GridView, id: string, change: GridItemChange): GridView;
7
+ /** Moves the item with `id` to place `to` in the order, the others closing up behind it — one place earlier or later
8
+ * (a button, a key), or wherever it is dropped. A place past either end, or the one it is in, leaves the order as it is. */
9
+ export declare function moveGridItem(doc: GridView, id: string, to: number): GridView;
10
+ /** The place of the item with `id` in the order, or -1. */
11
+ export declare function gridItemIndex(doc: GridView, id: string): number;
12
+ /** Removes the item with `id` — and, for a canvas, the triggers that name its nodes along with those naming it. */
13
+ export declare function removeGridItem(doc: GridView, id: string): GridView;
14
+ /** The canvas cell with `id` as a canvas board of its own — its spatial layer with what the board defines once —
15
+ * for the canvas editor to edit; `withCellCanvas` writes what it made back. */
16
+ export declare function cellAsCanvas(doc: GridView, id: string): CanvasView | null;
17
+ /** `doc` with the canvas cell `id` made `canvas`: the spatial layer goes to the cell, and what the board defines once
18
+ * — its elements, symbols, triggers, appearance and accent — to the board. */
19
+ export declare function withCellCanvas(doc: GridView, id: string, canvas: CanvasView): GridView;
@@ -0,0 +1,68 @@
1
+ import { isCanvasItem } from '@iyulab/u-board/picture';
2
+ import { triggersWithout, withTriggers } from './trigger-editing.js';
3
+ /** The item with `id` changed by `change` — a field set to `undefined` is left out, so the document says only what
4
+ * differs from the default. */
5
+ export function updateGridItem(doc, id, change) {
6
+ return {
7
+ ...doc,
8
+ items: doc.items.map(item => {
9
+ if (item.id !== id)
10
+ return item;
11
+ const next = { ...item, ...change };
12
+ for (const key of Object.keys(change))
13
+ if (next[key] === undefined)
14
+ delete next[key];
15
+ return next;
16
+ }),
17
+ };
18
+ }
19
+ /** Moves the item with `id` to place `to` in the order, the others closing up behind it — one place earlier or later
20
+ * (a button, a key), or wherever it is dropped. A place past either end, or the one it is in, leaves the order as it is. */
21
+ export function moveGridItem(doc, id, to) {
22
+ const from = doc.items.findIndex(item => item.id === id);
23
+ if (from < 0 || from === to || to < 0 || to >= doc.items.length)
24
+ return doc;
25
+ const items = [...doc.items];
26
+ const [moved] = items.splice(from, 1);
27
+ items.splice(to, 0, moved);
28
+ return { ...doc, items };
29
+ }
30
+ /** The place of the item with `id` in the order, or -1. */
31
+ export function gridItemIndex(doc, id) {
32
+ return doc.items.findIndex(item => item.id === id);
33
+ }
34
+ /** Removes the item with `id` — and, for a canvas, the triggers that name its nodes along with those naming it. */
35
+ export function removeGridItem(doc, id) {
36
+ const item = doc.items.find(existing => existing.id === id);
37
+ const gone = new Set([id, ...(item && isCanvasItem(item) ? item.canvas.nodes.map(node => node.id) : [])]);
38
+ return withTriggers({ ...doc, items: doc.items.filter(existing => existing.id !== id) }, triggersWithout(doc.triggers, gone));
39
+ }
40
+ /** The canvas cell with `id` as a canvas board of its own — its spatial layer with what the board defines once —
41
+ * for the canvas editor to edit; `withCellCanvas` writes what it made back. */
42
+ export function cellAsCanvas(doc, id) {
43
+ const item = doc.items.find(existing => existing.id === id);
44
+ if (!item || !isCanvasItem(item))
45
+ return null;
46
+ const board = Object.fromEntries(Object.entries(boardOf(doc)).filter(([, value]) => value !== undefined));
47
+ return { kind: 'canvas', ...item.canvas, ...board };
48
+ }
49
+ /** `doc` with the canvas cell `id` made `canvas`: the spatial layer goes to the cell, and what the board defines once
50
+ * — its elements, symbols, triggers, appearance and accent — to the board. */
51
+ export function withCellCanvas(doc, id, canvas) {
52
+ const { background, nodes, connectors, decorations } = canvas;
53
+ const cell = { background, nodes, connectors, ...(decorations && { decorations }) };
54
+ const items = doc.items.map(item => (item.id === id && isCanvasItem(item) ? { ...item, canvas: cell } : item));
55
+ const next = { ...doc, items };
56
+ for (const [key, value] of Object.entries(boardOf(canvas))) {
57
+ if (value === undefined)
58
+ delete next[key];
59
+ else
60
+ next[key] = value;
61
+ }
62
+ return next;
63
+ }
64
+ /** What a board defines once, whichever its kind. */
65
+ function boardOf(doc) {
66
+ const { appearance, accent, elements, symbols, triggers } = doc;
67
+ return { appearance, accent, elements, symbols, triggers };
68
+ }
@@ -0,0 +1,4 @@
1
+ import type { CanvasView } from '@iyulab/u-board/picture';
2
+ /** The document without these parts — nodes, decorations or connectors by id. A node takes the connectors that join
3
+ * it along: a line to nothing is not a board. */
4
+ export declare function removeParts(doc: CanvasView, ids: readonly string[]): CanvasView;
@@ -0,0 +1,11 @@
1
+ import { triggersWithout, withTriggers } from './trigger-editing.js';
2
+ /** The document without these parts — nodes, decorations or connectors by id. A node takes the connectors that join
3
+ * it along: a line to nothing is not a board. */
4
+ export function removeParts(doc, ids) {
5
+ const gone = new Set(ids);
6
+ const nodes = doc.nodes.filter(n => !gone.has(n.id));
7
+ const kept = new Set(nodes.map(n => n.id));
8
+ const connectors = doc.connectors.filter(c => !gone.has(c.id) && kept.has(c.fromNodeId) && kept.has(c.toNodeId));
9
+ const decorations = doc.decorations?.filter(d => !gone.has(d.id));
10
+ return withTriggers({ ...doc, nodes, connectors, ...(decorations && { decorations }) }, triggersWithout(doc.triggers, gone));
11
+ }
@@ -0,0 +1,16 @@
1
+ import type { Trigger, ViewDocument } from '@iyulab/u-board/picture';
2
+ /**
3
+ * A board's triggers once `parts` are gone: a trigger on one of them, or only while one of them is in a state, goes;
4
+ * an action bringing one into view is taken out, and a trigger left with nothing to do goes too. A trigger naming a
5
+ * part the board does not place is refused when the board is saved, so removing a part takes these with it.
6
+ * `undefined` when none is left.
7
+ */
8
+ export declare function triggersWithout(triggers: readonly Trigger[] | undefined, parts: ReadonlySet<string>): Trigger[] | undefined;
9
+ /** `doc` with `trigger` added at the end of its triggers. */
10
+ export declare function withTrigger<D extends ViewDocument>(doc: D, trigger: Trigger): D;
11
+ /** `doc` with the trigger at `index` replaced by `trigger`. */
12
+ export declare function replaceTrigger<D extends ViewDocument>(doc: D, index: number, trigger: Trigger): D;
13
+ /** `doc` without the trigger at `index` — and without a `triggers` list when that was the last. */
14
+ export declare function removeTrigger<D extends ViewDocument>(doc: D, index: number): D;
15
+ /** `doc` with `triggers` as its list, leaving the field out when there is none. */
16
+ export declare function withTriggers<D extends ViewDocument>(doc: D, triggers: readonly Trigger[] | undefined): D;
@@ -0,0 +1,36 @@
1
+ /**
2
+ * A board's triggers once `parts` are gone: a trigger on one of them, or only while one of them is in a state, goes;
3
+ * an action bringing one into view is taken out, and a trigger left with nothing to do goes too. A trigger naming a
4
+ * part the board does not place is refused when the board is saved, so removing a part takes these with it.
5
+ * `undefined` when none is left.
6
+ */
7
+ export function triggersWithout(triggers, parts) {
8
+ if (!triggers)
9
+ return undefined;
10
+ const kept = triggers.flatMap(trigger => {
11
+ if (('node' in trigger.on && parts.has(trigger.on.node)) || (trigger.when && parts.has(trigger.when.node)))
12
+ return [];
13
+ const actions = trigger.do.filter(action => !(action.action === 'focus' && parts.has(action.node)));
14
+ if (actions.length === 0)
15
+ return [];
16
+ return [actions.length === trigger.do.length ? trigger : { ...trigger, do: actions }];
17
+ });
18
+ return kept.length > 0 ? kept : undefined;
19
+ }
20
+ /** `doc` with `trigger` added at the end of its triggers. */
21
+ export function withTrigger(doc, trigger) {
22
+ return { ...doc, triggers: [...(doc.triggers ?? []), trigger] };
23
+ }
24
+ /** `doc` with the trigger at `index` replaced by `trigger`. */
25
+ export function replaceTrigger(doc, index, trigger) {
26
+ return { ...doc, triggers: (doc.triggers ?? []).map((t, i) => (i === index ? trigger : t)) };
27
+ }
28
+ /** `doc` without the trigger at `index` — and without a `triggers` list when that was the last. */
29
+ export function removeTrigger(doc, index) {
30
+ return withTriggers(doc, (doc.triggers ?? []).filter((_, i) => i !== index));
31
+ }
32
+ /** `doc` with `triggers` as its list, leaving the field out when there is none. */
33
+ export function withTriggers(doc, triggers) {
34
+ const { triggers: _, ...rest } = doc;
35
+ return (triggers && triggers.length > 0 ? { ...rest, triggers: [...triggers] } : rest);
36
+ }
@@ -0,0 +1,7 @@
1
+ export { BoardAuthoring } from './authoring/BoardAuthoring.js';
2
+ export type { BoardAuthoringProps } from './authoring/BoardAuthoring.js';
3
+ export { layoutEditable } from './authoring/board-layout.js';
4
+ export type { AuthoringMode } from './authoring/editor-parts.js';
5
+ export { DEFAULT_DESIGNER_LABELS, resolveDesignerLabels } from './labels.js';
6
+ export type { AuthoringLabels, DesignerLabels } from './labels.js';
7
+ export { KO_DESIGNER_LABELS } from './labels-ko.js';
@@ -0,0 +1,5 @@
1
+ // The authoring tool: a board edited in place, over the viewer's own building blocks.
2
+ export { BoardAuthoring } from './authoring/BoardAuthoring.js';
3
+ export { layoutEditable } from './authoring/board-layout.js';
4
+ export { DEFAULT_DESIGNER_LABELS, resolveDesignerLabels } from './labels.js';
5
+ export { KO_DESIGNER_LABELS } from './labels-ko.js';
@@ -0,0 +1,4 @@
1
+ import type { AuthoringLabels, DesignerLabels } from './labels.js';
2
+ export declare const KO_AUTHORING_LABELS: AuthoringLabels;
3
+ /** Every label in Korean — what `BoardAuthoring` shows when given `labels: KO_DESIGNER_LABELS`. */
4
+ export declare const KO_DESIGNER_LABELS: DesignerLabels;
@@ -0,0 +1,270 @@
1
+ import { KO_LABELS } from '@iyulab/u-board/viewer';
2
+ export const KO_AUTHORING_LABELS = {
3
+ editCanvas: '캔버스 편집',
4
+ backToGrid: '← 그리드',
5
+ editGridCell: '칸 그리드 편집',
6
+ layoutWidth: '배치 폭',
7
+ layoutWide: '넓게',
8
+ layoutMedium: '중간',
9
+ layoutNarrow: '좁게',
10
+ addConnector: '연결선 추가',
11
+ connectHint: '연결할 두 노드를 선택하세요(두 번째는 Shift+클릭).',
12
+ deleteSelected: '삭제',
13
+ undo: '실행 취소',
14
+ partAdd: '부품 추가',
15
+ newPartTitle: '새 부품',
16
+ redo: '다시 실행',
17
+ save: '저장',
18
+ export: '내보내기',
19
+ import: '가져오기',
20
+ boardHeading: '보드',
21
+ setBackground: '배경 이미지',
22
+ referencePoints: '기준점',
23
+ referencePointsHint: '이미지의 두 점과 그 점이 나타내는 좌표 — 지도라면 경도·위도, 평면도라면 미터. 그러면 고정한 노드의 자리를 좌표로 읽습니다.',
24
+ referencePoint: '기준점 {n}',
25
+ imageX: '이미지 x',
26
+ imageY: '이미지 y',
27
+ coordinateX: '좌표 x',
28
+ coordinateY: '좌표 y',
29
+ referencePointsApart: '두 점은 이미지에서도 좌표에서도 두 축 모두 달라야 합니다.',
30
+ referencePointsIncomplete: '여덟 칸을 모두 채우면 저장됩니다 — 그 전까지는 저장된 기준점이 그대로입니다.',
31
+ clearReferencePoints: '기준점 지우기',
32
+ referencePointsNeeded: '이전 기준점은 이 이미지에 맞지 않아 지웠습니다. 기준점을 다시 정하세요 — 고정한 노드가 있다면 그 뒤 원래 좌표에 다시 놓을 수 있습니다.',
33
+ anchorsMoved: '고정한 노드 {count}개가 원래 좌표에서 벗어났습니다.',
34
+ relocateAnchors: '좌표 그대로 다시 놓기',
35
+ keepAnchors: '이대로 두기',
36
+ removeBackground: '배경 제거',
37
+ appearance: '바탕',
38
+ appearanceLight: '밝게',
39
+ appearanceDark: '어둡게',
40
+ accent: '강조색',
41
+ accentPlaceholder: '테마 기본',
42
+ backgroundType: 'PNG, JPEG, WebP, GIF, SVG 이미지를 고르세요.',
43
+ backgroundTooLarge: '이미지가 {max}보다 큽니다.',
44
+ backgroundUnreadable: '이미지를 읽지 못했습니다.',
45
+ mode: '모드',
46
+ editMode: '편집',
47
+ viewMode: '보기',
48
+ editorRegion: '편집기',
49
+ previewRegion: '보드 보기',
50
+ selectNode: '노드나 장식을 선택하면 여기서 편집합니다.',
51
+ itemLayout: '배치',
52
+ itemSpan: '너비({columns}열 중)',
53
+ itemSpanMedium: '중간 폭에서 너비({columns}열 중)',
54
+ itemSpanMediumAuto: '자동 — 전체 폭의 줄 그대로',
55
+ itemRowSpan: '차지하는 줄 수',
56
+ itemHeight: '높이(px)',
57
+ itemHeightAuto: '위젯 기본 높이',
58
+ canvasHeightAuto: '캔버스 비율대로',
59
+ moveEarlier: '앞으로',
60
+ moveLater: '뒤로',
61
+ duplicateItem: '항목 복제',
62
+ removeItem: '항목 삭제',
63
+ multipleSelected: '{count}개 선택됨 — 하나를 선택하면 편집할 수 있습니다.',
64
+ layoutOnlyHint: '여기서는 부품을 옮기고 크기를 바꾸거나 지울 수 있습니다. 부품을 선택하면 설정을 고칠 수 있습니다.',
65
+ partHeading: '부품 {id}',
66
+ linkHeading: '연결선 {from} → {to}',
67
+ shapeHeading: '도형 {id}',
68
+ shapeAddBox: '틀 추가',
69
+ shapeAddText: '글 추가',
70
+ shapeAddLine: '선 도형 추가',
71
+ shapePoints: '점(x,y — 빈칸으로)',
72
+ shapePointsInvalid: '점 둘 이상을 x,y로, 빈칸으로 이어 적으세요: 20,20 220,20.',
73
+ shapePath: '경로(M · L · C · Q · Z, 절대 좌표)',
74
+ shapeNewText: '글',
75
+ shapeLabel: '이름표',
76
+ shapeText: '글',
77
+ shapeSize: '글자 크기',
78
+ shapeWidth: '선 굵기',
79
+ shapeTone: '톤',
80
+ linkLabel: '라벨',
81
+ linkReads: '읽는 항목(상태를 위해)',
82
+ linkShows: '상태 필드',
83
+ linkTone: '상태가 없을 때의 톤',
84
+ linkToneNone: '(대기)',
85
+ linkRoute: '경로',
86
+ linkArrow: '화살표',
87
+ linkDash: '점선',
88
+ partTitle: '제목',
89
+ partKind: '종류',
90
+ partFromPreset: '(프리셋에서)',
91
+ partOf: '읽는 데이터',
92
+ partOfNone: '(없음)',
93
+ partItem: '항목(키)',
94
+ partItemAll: '모든 항목',
95
+ partShow: '보일 필드(쉼표로)',
96
+ partEach: '{data}의 항목마다 하나씩 그려지는 부품입니다.',
97
+ partOwnOptions: '종류의 옵션',
98
+ partWidgetOptions: '위젯 옵션',
99
+ partStructured: '구조로 쓰인 값입니다 — AI 비서나 보드 JSON으로 고칩니다.',
100
+ boardNotDrawn: '지금 설정으로는 보드를 그릴 수 없습니다 — {reason}. 그릴 수 있었던 마지막 모습을 보여 줍니다.',
101
+ statusesHeading: '상태',
102
+ statusTone: '톤',
103
+ statusLabel: '이름표',
104
+ statusGlyph: '표시 기호',
105
+ statusEmphasis: '강조',
106
+ statusEmphasisNone: '(없음)',
107
+ statusRemove: '{name} 지우기',
108
+ statusNew: '새 상태',
109
+ statusAdd: '상태 추가',
110
+ dataHeading: '데이터',
111
+ dataFrom: '원천',
112
+ dataPath: '요청 경로',
113
+ dataByRef: '어댑터의 참조로 읽는 데이터입니다 — AI 비서나 보드 JSON으로 고칩니다.',
114
+ dataList: '응답 속 목록(JSON Pointer)',
115
+ dataKey: '항목의 키 필드',
116
+ dataDetails: '읽기 상세',
117
+ dataWhere: '이 값의 항목만(필드=값, 쉼표로)',
118
+ dataWhereInvalid: '필드=값을 쉼표로 이어 적으세요: kind=PM10, site=north.',
119
+ dataTime: '항목을 관측한 시각의 필드',
120
+ dataAnswerTime: '답 전체를 관측한 시각(JSON Pointer)',
121
+ dataFresh: '값이 현재로 남는 초',
122
+ dataZone: '원천이 시각을 쓰는 시간대(IANA)',
123
+ dataNowDelay: '요청 시각 — 원천이 자료를 갖기까지 초',
124
+ dataNowStep: '요청 시각 — 원천 자료의 간격 초',
125
+ dataPivotKey: '이름마다 한 행 — 이름의 필드',
126
+ dataPivotValue: '이름마다 한 행 — 값의 필드',
127
+ dataFields: '필드',
128
+ dataFieldLabel: '이름',
129
+ dataFieldUnit: '단위',
130
+ dataFieldDigits: '소수 자리',
131
+ dataFieldFormat: '서식',
132
+ dataFieldRemove: '필드 {name} 지우기',
133
+ dataFieldState: '상태',
134
+ dataFieldStateRelative: '상태가 시계를 따름(지금부터 그 시각까지의 초에 대한 구간) — 보드 JSON에서 고친다',
135
+ dataFieldNames: '낱말',
136
+ mappingNone: '(없음)',
137
+ mappingRaw: '값이 곧 상태 이름',
138
+ mappingMap: '값마다',
139
+ mappingBands: '숫자 띠',
140
+ mappingFrom: '값 {n}',
141
+ mappingTo: '이름 {n}',
142
+ mappingAddRow: '값 추가',
143
+ mappingOtherwise: '그 밖의 값',
144
+ mappingBandsText: '이름과 경계를 번갈아(ok, 1, warn, 5, alarm)',
145
+ mappingBandsInvalid: '이름부터, 이름과 커지는 숫자를 번갈아 적으세요: ok, 1, warn, 5, alarm.',
146
+ dataFieldNew: '새 필드',
147
+ dataFieldAdd: '필드 추가',
148
+ dataLook: '데이터 살펴보기',
149
+ dataLooking: '읽는 중…',
150
+ dataFound: '찾은 필드',
151
+ dataFoundAdd: '{name} 더하기',
152
+ dataFoundNone: '읽은 것이 없습니다 — 원천과 요청 경로를 확인하세요.',
153
+ dataRemove: '{name} 지우기',
154
+ dataNew: '새 데이터',
155
+ dataAdd: '데이터 추가',
156
+ widgetType: '위젯 타입',
157
+ widgetData: '데이터',
158
+ widgetOptions: '표시',
159
+ elementProps: '요소 속성',
160
+ boardElements: '이 보드의 요소',
161
+ elementsHeading: '요소',
162
+ addElement: '새 요소',
163
+ elementName: '이름',
164
+ elementTemplate: '템플릿',
165
+ elementScript: '스크립트',
166
+ elementStyle: 'CSS',
167
+ elementHeight: '높이(px)',
168
+ elementScriptPreview: '스크립트 요소는 저장된 보드에서 그려집니다 — 저장하면 보입니다.',
169
+ removeElement: '요소 삭제',
170
+ removeElementPlaced: '{count}곳에 배치돼 있습니다 — 먼저 그 위젯을 바꾸거나 지우세요.',
171
+ elementPropRemove: '{name} 지우기',
172
+ elementPropNew: '새 prop',
173
+ elementPropAdd: 'prop 추가',
174
+ boundField: '바인딩됨',
175
+ choiceDefault: '기본값',
176
+ advancedProps: '고급: JSON으로 편집',
177
+ moreInAdvanced: '고급에서 설정할 옵션: {count}개',
178
+ noDataSources: '연결된 데이터소스가 없습니다.',
179
+ propPath: '프롭 경로',
180
+ choosePropPath: '연결할 값을 고르세요',
181
+ otherPropPath: '다른 경로…',
182
+ typedPropPath: '위젯 props 안의 경로',
183
+ reference: '참조',
184
+ chooseReference: '참조를 고르세요',
185
+ path: '요청 경로',
186
+ pickItemBy: '목록 항목을 고르는 기준',
187
+ pickItemByPosition: '목록 안 순서(지금처럼)',
188
+ listItem: '목록 항목',
189
+ clearListItem: '순서로 고르기',
190
+ observedAt: '관측 시각',
191
+ observedAtWhenRead: '읽은 시각',
192
+ observedAtHint: '응답을 탐색하면 원천이 관측 시각을 적은 필드를 고를 수 있습니다.',
193
+ timeZone: '원천의 시간대',
194
+ unknownTimeZone: 'Asia/Seoul이나 UTC 같은 시간대를 입력하세요.',
195
+ observedAtReads: '읽은 결과: {time} — {age}',
196
+ observedAtLater: '지금보다 늦은 시각입니다 — 시간대를 확인하세요.',
197
+ requestTime: '묻는 시각',
198
+ maxAge: '정상일 때 최대 나이(분)',
199
+ maxAgeHint: '원천 시각으로 이보다 오래되면 «원천 갱신 늦음»으로 보입니다. 원천에는 이 시간의 8분의 1보다 자주 다시 묻지 않습니다.',
200
+ invalidMaxAge: '0보다 큰 분 수를 입력하거나 비워 두세요.',
201
+ keyInPath: '이 경로에 키가 들어 있는 것 같습니다. 보드는 경로를 그대로 저장하고 공유 링크는 그것을 보여 줍니다 — 키는 데이터소스의 인증 방식으로 보내세요.',
202
+ valuePath: '값 경로',
203
+ explore: '탐색',
204
+ wholeResponse: '(전체 응답)',
205
+ bindingNeedsPropPath: '연결할 프롭 경로를 입력하세요.',
206
+ bindingNeedsReference: '참조를 고르세요.',
207
+ valueMapHeading: '값 매핑',
208
+ mapFrom: '원천 값 {n}',
209
+ mapTo: '표시 값 {n}',
210
+ addMapping: '매핑 추가',
211
+ removeMapping: '매핑 {n} 삭제',
212
+ rangeMin: '구간 {n} 이상',
213
+ rangeMax: '구간 {n} 미만',
214
+ rangeTo: '구간 {n} 표시 값',
215
+ addRange: '구간 추가',
216
+ removeRange: '구간 {n} 삭제',
217
+ rangeInvalid: '구간 {n}: 이상·미만 중 하나 이상을 적고, 둘 다 적으면 미만이 더 커야 합니다.',
218
+ mapOtherwise: '그 밖의 값',
219
+ mapOtherwisePlaceholder: '받은 그대로',
220
+ statesHeading: '상태',
221
+ statesNeedBinding: '먼저 값을 바인딩하세요 — 부품의 상태는 위젯 바인딩 하나에서 읽습니다.',
222
+ statesFrom: '읽을 값',
223
+ statesNone: '상태 없음',
224
+ statesMapHeading: '값 → 상태',
225
+ stateForValue: '값 {n}의 상태',
226
+ stateForRange: '범위 {n}의 상태',
227
+ statesLooks: '상태별 모양',
228
+ stateOutline: '테두리 색 — {state}',
229
+ stateBlink: '깜박임 — {state}',
230
+ stateHidden: '숨김 — {state}',
231
+ removeStates: '상태 지우기',
232
+ triggersHeading: '트리거',
233
+ triggersOnOpenHeading: '보드가 열릴 때',
234
+ triggerHeading: '트리거 {n}',
235
+ triggerEvent: '언제',
236
+ triggerOnClick: '클릭할 때',
237
+ triggerOnElement: '요소가 이벤트를 낼 때',
238
+ triggerOnEnter: '상태에 들어갈 때',
239
+ triggerOnLeave: '상태에서 나올 때',
240
+ triggerEventName: '이벤트 이름',
241
+ triggerState: '상태',
242
+ triggerOnlyWhen: '어떤 부품이 특정 상태일 때만',
243
+ triggerEveryItem: '{part}의 모든 항목에',
244
+ triggerWhenPart: '부품',
245
+ triggerWhenState: '상태(여럿이면 쉼표로)',
246
+ triggerAction: '동작 {n}',
247
+ triggerOpenLink: '링크 열기',
248
+ triggerFocus: '부품으로 이동',
249
+ triggerEmit: '페이지에 알리기',
250
+ triggerGoToBoard: '다른 보드 보기',
251
+ triggerFocusPart: '이동할 부품 {n}',
252
+ triggerLinkUrl: '링크 {n}',
253
+ triggerEmitName: '이벤트 이름 {n}',
254
+ triggerBoardId: '보드 id {n}',
255
+ removeTriggerAction: '동작 {n} 지우기',
256
+ addTriggerAction: '동작 추가',
257
+ removeTrigger: '트리거 {n} 지우기',
258
+ addTrigger: '트리거 추가',
259
+ triggerIncomplete: '칸을 모두 채우세요 — 트리거는 완성되면 저장됩니다.',
260
+ triggerLinkRefused: '링크는 https:// 주소나 이 설치의 경로(/…)여야 합니다.',
261
+ mapped: '매핑됨',
262
+ previewLive: '정상',
263
+ arrowNone: '없음',
264
+ arrowEnd: '{to} 쪽으로',
265
+ arrowStart: '{from} 쪽으로',
266
+ arrowBoth: '양쪽',
267
+ arrowFromField: '{field} 값에 따라',
268
+ };
269
+ /** Every label in Korean — what `BoardAuthoring` shows when given `labels: KO_DESIGNER_LABELS`. */
270
+ export const KO_DESIGNER_LABELS = { ...KO_LABELS, ...KO_AUTHORING_LABELS };