@things-factory/integration-ui 6.1.116 → 6.1.118

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/integration-ui",
3
- "version": "6.1.116",
3
+ "version": "6.1.118",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -37,11 +37,11 @@
37
37
  "@operato/property-editor": "^1.0.0",
38
38
  "@operato/styles": "^1.0.0",
39
39
  "@operato/utils": "^1.0.1",
40
- "@things-factory/export-base": "^6.1.116",
41
- "@things-factory/import-base": "^6.1.116",
42
- "@things-factory/integration-base": "^6.1.116",
40
+ "@things-factory/export-base": "^6.1.118",
41
+ "@things-factory/import-base": "^6.1.118",
42
+ "@things-factory/integration-base": "^6.1.118",
43
43
  "d3": "^7.8.5",
44
44
  "moment-timezone": "^0.5.40"
45
45
  },
46
- "gitHead": "4477d162a7008239bfd5f31dcfa879f59a2ad2ce"
46
+ "gitHead": "ea96bacb831bdc751bd1962a9d73a7d8abf0e304"
47
47
  }
@@ -1,37 +0,0 @@
1
- /**
2
- * @license Copyright © HatioLab Inc. All rights reserved.
3
- */
4
- import '@material/mwc-icon';
5
- import { OxFormField } from '@operato/input';
6
- type NameType = {
7
- [name: string]: string;
8
- };
9
- type ArrayedNameType = {
10
- name: string;
11
- type: any;
12
- };
13
- /**
14
- input component for key-value map
15
-
16
- Example:
17
-
18
- <things-editor-procedure-output
19
- value=${map}
20
- </things-editor-procedure-output>
21
- */
22
- export declare class ThingsEditorProcedureOutput extends OxFormField {
23
- static styles: import("lit").CSSResult;
24
- value: NameType;
25
- private _changingNow;
26
- firstUpdated(): void;
27
- render(): import("lit-html").TemplateResult<1>;
28
- _onChange(e: Event): void;
29
- _build(includeNewRecord?: boolean): void;
30
- _toArray(map: NameType): ArrayedNameType[];
31
- _add(): void;
32
- _delete(e: MouseEvent): void;
33
- records: NodeListOf<HTMLElement>;
34
- _up(e: MouseEvent): void;
35
- _down(e: MouseEvent): void;
36
- }
37
- export {};
@@ -1,234 +0,0 @@
1
- /**
2
- * @license Copyright © HatioLab Inc. All rights reserved.
3
- */
4
- import { __decorate, __metadata } from "tslib";
5
- import '@material/mwc-icon';
6
- import { css, html } from 'lit';
7
- import { customElement, property, queryAll } from 'lit/decorators.js';
8
- import { OxFormField } from '@operato/input';
9
- /**
10
- input component for key-value map
11
-
12
- Example:
13
-
14
- <things-editor-procedure-output
15
- value=${map}
16
- </things-editor-procedure-output>
17
- */
18
- let ThingsEditorProcedureOutput = class ThingsEditorProcedureOutput extends OxFormField {
19
- constructor() {
20
- super(...arguments);
21
- this.value = {};
22
- this._changingNow = false;
23
- }
24
- firstUpdated() {
25
- this.renderRoot.addEventListener('change', this._onChange.bind(this));
26
- }
27
- render() {
28
- const value = !this.value || typeof this.value !== 'object' ? {} : this.value;
29
- return html `
30
- ${this._toArray(value).map(item => html `
31
- <div data-record>
32
- <input type="text" data-name placeholder="name" .value=${item.name} />
33
- <select data-type placeholder="type" .value=${item.type}>
34
- <option value="" ?selected=${item.type == ''}>&nbsp;</option>
35
- <option value="String" ?selected=${item.type == 'String'}>String</option>
36
- <option value="Number" ?selected=${item.type == 'Number'}>Number</option>
37
- <option value="Cursor" ?selected=${item.type == 'Cursor'}>Cursor</option>
38
- </select>
39
- <button class="record-action" @click=${(e) => this._delete(e)} tabindex="-1">
40
- <mwc-icon>remove</mwc-icon>
41
- </button>
42
- <button class="record-action" @click=${(e) => this._up(e)} tabindex="-1">
43
- <mwc-icon>arrow_upward</mwc-icon>
44
- </button>
45
- <button class="record-action" @click=${(e) => this._down(e)} tabindex="-1">
46
- <mwc-icon>arrow_downward</mwc-icon>
47
- </button>
48
- </div>
49
- `)}
50
-
51
- <div data-record-new>
52
- <input type="text" data-name placeholder="name" value="" />
53
- <select data-type placeholder="type">
54
- <option value="">&nbsp;</option>
55
- <option value="String">String</option>
56
- <option value="Number">Number</option>
57
- <option value="Cursor">Cursor</option>
58
- </select>
59
- <button class="record-action" @click=${(e) => this._add()} tabindex="-1">
60
- <mwc-icon>add</mwc-icon>
61
- </button>
62
- <button class="hidden"><mwc-icon>add</mwc-icon></button>
63
- <button class="hidden"><mwc-icon>add</mwc-icon></button>
64
- </div>
65
- `;
66
- }
67
- _onChange(e) {
68
- if (this._changingNow) {
69
- return;
70
- }
71
- this._changingNow = true;
72
- const input = e.target;
73
- const record = e.target.closest('[data-record],[data-record-new]');
74
- if (record.hasAttribute('data-record')) {
75
- this._build();
76
- }
77
- else if (record.hasAttribute('data-record-new') && input.hasAttribute('data-type')) {
78
- this._add();
79
- }
80
- this._changingNow = false;
81
- }
82
- _build(includeNewRecord) {
83
- if (includeNewRecord) {
84
- var records = this.renderRoot.querySelectorAll('[data-record],[data-record-new]');
85
- }
86
- else {
87
- var records = this.renderRoot.querySelectorAll('[data-record]');
88
- }
89
- var newmap = {};
90
- for (var i = 0; i < records.length; i++) {
91
- var record = records[i];
92
- const name = record.querySelector('[data-name]').value;
93
- const inputs = record.querySelectorAll('[data-type]:not([style*="display: none"])');
94
- if (!inputs || inputs.length == 0) {
95
- continue;
96
- }
97
- var input = inputs[inputs.length - 1];
98
- var value = input.value;
99
- if (name) {
100
- newmap[name] = value || '';
101
- }
102
- }
103
- this.value = newmap;
104
- this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }));
105
- }
106
- /* map아이템들을 template(dom-repeat)용 배열로 변환하는 함수 */
107
- _toArray(map) {
108
- var array = [];
109
- for (var name in map) {
110
- array.push({
111
- name: name,
112
- type: map[name]
113
- });
114
- }
115
- return array;
116
- }
117
- _add() {
118
- this._build(true);
119
- const inputs = this.renderRoot.querySelectorAll('[data-record-new] input:not([style*="display: none"])');
120
- for (var i = 0; i < inputs.length; i++) {
121
- let input = inputs[i];
122
- input.value = '';
123
- }
124
- inputs[0].focus();
125
- }
126
- _delete(e) {
127
- const record = e.target.closest('[data-record]');
128
- record.querySelector('[data-name]').value = '';
129
- this._build();
130
- }
131
- _up(e) {
132
- const record = e.target.closest('[data-record]');
133
- const array = Array.from(this.records);
134
- const index = array.indexOf(record) - 1;
135
- if (index < 0) {
136
- return;
137
- }
138
- const deleted = array.splice(index, 1);
139
- array.splice(index + 1, 0, ...deleted);
140
- this.value = array.reduce((sum, record) => {
141
- const name = record.querySelector('[data-name]').value;
142
- const type = record.querySelector('[data-type]').value;
143
- sum[name] = type;
144
- return sum;
145
- }, {});
146
- this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }));
147
- }
148
- _down(e) {
149
- const record = e.target.closest('[data-record]');
150
- const array = Array.from(this.records);
151
- const index = array.indexOf(record);
152
- if (index > array.length) {
153
- return;
154
- }
155
- array.splice(index, 1);
156
- array.splice(index + 1, 0, record);
157
- this.value = array.reduce((sum, record) => {
158
- const name = record.querySelector('[data-name]').value;
159
- const type = record.querySelector('[data-type]').value;
160
- sum[name] = type;
161
- return sum;
162
- }, {});
163
- this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }));
164
- }
165
- };
166
- ThingsEditorProcedureOutput.styles = css `
167
- :host {
168
- display: flex;
169
- flex-direction: column;
170
- overflow: hidden;
171
- margin-bottom: var(--margin-wide);
172
- }
173
-
174
- div {
175
- display: flex;
176
- flex-flow: row nowrap;
177
- gap: var(--margin-default);
178
- margin-bottom: var(--margin-narrow);
179
- }
180
-
181
- button {
182
- border: var(--button-border);
183
- border-radius: var(--border-radius);
184
- background-color: var(--button-background-color);
185
- padding: var(--padding-narrow) var(--padding-default);
186
- line-height: 0.8;
187
- color: var(--button-color);
188
- cursor: pointer;
189
- }
190
- button + button {
191
- margin-left: -5px;
192
- }
193
- button mwc-icon {
194
- font-size: var(--fontsize-default);
195
- }
196
- button:focus,
197
- button:hover,
198
- button:active {
199
- border: var(--button-activ-border);
200
- background-color: var(--button-background-focus-color);
201
- color: var(--theme-white-color);
202
- }
203
-
204
- input {
205
- flex: 1;
206
- border: 0;
207
- border-bottom: var(--border-dark-color);
208
- padding: var(--input-padding);
209
- font: var(--input-font);
210
- color: var(--primary-text-color);
211
- min-width: 50px;
212
- }
213
- input:focus {
214
- outline: none;
215
- border-bottom: 1px solid var(--primary-color);
216
- }
217
- button.hidden {
218
- opacity: 0;
219
- cursor: default;
220
- }
221
- `;
222
- __decorate([
223
- property({ type: Object }),
224
- __metadata("design:type", Object)
225
- ], ThingsEditorProcedureOutput.prototype, "value", void 0);
226
- __decorate([
227
- queryAll('[data-record]'),
228
- __metadata("design:type", Object)
229
- ], ThingsEditorProcedureOutput.prototype, "records", void 0);
230
- ThingsEditorProcedureOutput = __decorate([
231
- customElement('things-editor-procedure-output')
232
- ], ThingsEditorProcedureOutput);
233
- export { ThingsEditorProcedureOutput };
234
- //# sourceMappingURL=things-editor-procedure-output.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"things-editor-procedure-output.js","sourceRoot":"","sources":["../../client/editors/things-editor-procedure-output.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license Copyright © HatioLab Inc. All rights reserved.\n */\n\nimport '@material/mwc-icon'\n\nimport { css, html } from 'lit'\nimport { customElement, property, queryAll } from 'lit/decorators.js'\n\nimport { OxFormField } from '@operato/input'\n\ntype NameType = { [name: string]: string }\ntype ArrayedNameType = { name: string; type: any }\n\n/**\n input component for key-value map\n \n Example:\n \n <things-editor-procedure-output \n value=${map}\n </things-editor-procedure-output>\n */\n@customElement('things-editor-procedure-output')\nexport class ThingsEditorProcedureOutput extends OxFormField {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n margin-bottom: var(--margin-wide);\n }\n\n div {\n display: flex;\n flex-flow: row nowrap;\n gap: var(--margin-default);\n margin-bottom: var(--margin-narrow);\n }\n\n button {\n border: var(--button-border);\n border-radius: var(--border-radius);\n background-color: var(--button-background-color);\n padding: var(--padding-narrow) var(--padding-default);\n line-height: 0.8;\n color: var(--button-color);\n cursor: pointer;\n }\n button + button {\n margin-left: -5px;\n }\n button mwc-icon {\n font-size: var(--fontsize-default);\n }\n button:focus,\n button:hover,\n button:active {\n border: var(--button-activ-border);\n background-color: var(--button-background-focus-color);\n color: var(--theme-white-color);\n }\n\n input {\n flex: 1;\n border: 0;\n border-bottom: var(--border-dark-color);\n padding: var(--input-padding);\n font: var(--input-font);\n color: var(--primary-text-color);\n min-width: 50px;\n }\n input:focus {\n outline: none;\n border-bottom: 1px solid var(--primary-color);\n }\n button.hidden {\n opacity: 0;\n cursor: default;\n }\n `\n\n @property({ type: Object }) value: NameType = {}\n\n private _changingNow: boolean = false\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', this._onChange.bind(this))\n }\n\n render() {\n const value = !this.value || typeof this.value !== 'object' ? {} : this.value\n\n return html`\n ${this._toArray(value).map(\n item => html`\n <div data-record>\n <input type=\"text\" data-name placeholder=\"name\" .value=${item.name} />\n <select data-type placeholder=\"type\" .value=${item.type}>\n <option value=\"\" ?selected=${item.type == ''}>&nbsp;</option>\n <option value=\"String\" ?selected=${item.type == 'String'}>String</option>\n <option value=\"Number\" ?selected=${item.type == 'Number'}>Number</option>\n <option value=\"Cursor\" ?selected=${item.type == 'Cursor'}>Cursor</option>\n </select>\n <button class=\"record-action\" @click=${(e: MouseEvent) => this._delete(e)} tabindex=\"-1\">\n <mwc-icon>remove</mwc-icon>\n </button>\n <button class=\"record-action\" @click=${(e: MouseEvent) => this._up(e)} tabindex=\"-1\">\n <mwc-icon>arrow_upward</mwc-icon>\n </button>\n <button class=\"record-action\" @click=${(e: MouseEvent) => this._down(e)} tabindex=\"-1\">\n <mwc-icon>arrow_downward</mwc-icon>\n </button>\n </div>\n `\n )}\n\n <div data-record-new>\n <input type=\"text\" data-name placeholder=\"name\" value=\"\" />\n <select data-type placeholder=\"type\">\n <option value=\"\">&nbsp;</option>\n <option value=\"String\">String</option>\n <option value=\"Number\">Number</option>\n <option value=\"Cursor\">Cursor</option>\n </select>\n <button class=\"record-action\" @click=${(e: MouseEvent) => this._add()} tabindex=\"-1\">\n <mwc-icon>add</mwc-icon>\n </button>\n <button class=\"hidden\"><mwc-icon>add</mwc-icon></button>\n <button class=\"hidden\"><mwc-icon>add</mwc-icon></button>\n </div>\n `\n }\n\n _onChange(e: Event) {\n if (this._changingNow) {\n return\n }\n\n this._changingNow = true\n\n const input = e.target as HTMLInputElement\n\n const record = (e.target as Element).closest('[data-record],[data-record-new]') as HTMLElement\n\n if (record.hasAttribute('data-record')) {\n this._build()\n } else if (record.hasAttribute('data-record-new') && input.hasAttribute('data-type')) {\n this._add()\n }\n\n this._changingNow = false\n }\n\n _build(includeNewRecord?: boolean) {\n if (includeNewRecord) {\n var records = this.renderRoot.querySelectorAll('[data-record],[data-record-new]') as NodeListOf<HTMLElement>\n } else {\n var records = this.renderRoot.querySelectorAll('[data-record]') as NodeListOf<HTMLElement>\n }\n\n var newmap: NameType = {}\n\n for (var i = 0; i < records.length; i++) {\n var record = records[i]\n\n const name = (record.querySelector('[data-name]') as HTMLInputElement).value\n const inputs = record.querySelectorAll(\n '[data-type]:not([style*=\"display: none\"])'\n ) as NodeListOf<HTMLInputElement>\n\n if (!inputs || inputs.length == 0) {\n continue\n }\n\n var input = inputs[inputs.length - 1]\n\n var value = input.value\n\n if (name) {\n newmap[name] = value || ''\n }\n }\n\n this.value = newmap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n /* map아이템들을 template(dom-repeat)용 배열로 변환하는 함수 */\n _toArray(map: NameType) {\n var array: ArrayedNameType[] = []\n\n for (var name in map) {\n array.push({\n name: name,\n type: map[name]\n })\n }\n\n return array\n }\n\n _add() {\n this._build(true)\n\n const inputs = this.renderRoot.querySelectorAll(\n '[data-record-new] input:not([style*=\"display: none\"])'\n ) as NodeListOf<HTMLInputElement & { value: any }>\n\n for (var i = 0; i < inputs.length; i++) {\n let input = inputs[i]\n\n input.value = ''\n }\n\n inputs[0].focus()\n }\n\n _delete(e: MouseEvent) {\n const record = (e.target as Element).closest('[data-record]') as HTMLElement\n\n ;(record!.querySelector('[data-name]') as HTMLInputElement)!.value = ''\n\n this._build()\n }\n\n @queryAll('[data-record]') records!: NodeListOf<HTMLElement>\n\n _up(e: MouseEvent) {\n const record = (e.target as Element).closest('[data-record]') as HTMLElement\n const array = Array.from(this.records)\n const index = array.indexOf(record) - 1\n\n if (index < 0) {\n return\n }\n\n const deleted = array.splice(index, 1)\n array.splice(index + 1, 0, ...deleted)\n\n this.value = array.reduce((sum, record) => {\n const name = (record.querySelector('[data-name]') as HTMLInputElement).value\n const type = (record.querySelector('[data-type]') as HTMLInputElement).value\n\n sum[name] = type\n return sum\n }, {} as { [name: string]: string })\n\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n _down(e: MouseEvent) {\n const record = (e.target as Element).closest('[data-record]') as HTMLElement\n const array = Array.from(this.records)\n const index = array.indexOf(record)\n\n if (index > array.length) {\n return\n }\n\n array.splice(index, 1)\n array.splice(index + 1, 0, record)\n\n this.value = array.reduce((sum, record) => {\n const name = (record.querySelector('[data-name]') as HTMLInputElement).value\n const type = (record.querySelector('[data-type]') as HTMLInputElement).value\n\n sum[name] = type\n return sum\n }, {} as { [name: string]: string })\n\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n}\n"]}