@fmsim/layout-view 2.0.0-beta.21 → 2.0.0-beta.23
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/dist-client/data-grist/ox-input-animation-map.js +4 -4
- package/dist-client/data-grist/ox-input-animation-map.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/translations/en.json +4 -1
- package/translations/ja.json +4 -1
- package/translations/ko.json +4 -1
- package/translations/ms.json +4 -1
- package/translations/zh.json +4 -1
|
@@ -84,9 +84,9 @@ let OxInputAnimationMap = class OxInputAnimationMap extends LitElement {
|
|
|
84
84
|
const entry = this._parsed[idx];
|
|
85
85
|
if (!entry)
|
|
86
86
|
return;
|
|
87
|
-
//
|
|
87
|
+
// 항상 { animation: config } 구조로 저장 (원본에 다른 키가 있으면 보존)
|
|
88
88
|
const newEntryValue = entry.isNested
|
|
89
|
-
? Object.assign(Object.assign({}, entry.full), { animation: e.detail }) : e.detail;
|
|
89
|
+
? Object.assign(Object.assign({}, entry.full), { animation: e.detail }) : { animation: e.detail };
|
|
90
90
|
this.value = Object.assign(Object.assign({}, this.value), { [entry.key]: newEntryValue });
|
|
91
91
|
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }));
|
|
92
92
|
}
|
|
@@ -116,7 +116,7 @@ let OxInputAnimationMap = class OxInputAnimationMap extends LitElement {
|
|
|
116
116
|
const animConfig = (configEl === null || configEl === void 0 ? void 0 : configEl.value) || {};
|
|
117
117
|
const entry = this._parsed[idx];
|
|
118
118
|
newMap[key] = (entry === null || entry === void 0 ? void 0 : entry.isNested)
|
|
119
|
-
? Object.assign(Object.assign({}, entry.full), { animation: animConfig }) : animConfig;
|
|
119
|
+
? Object.assign(Object.assign({}, entry.full), { animation: animConfig }) : { animation: animConfig };
|
|
120
120
|
});
|
|
121
121
|
if (((_a = this.value) === null || _a === void 0 ? void 0 : _a.default) !== undefined) {
|
|
122
122
|
newMap.default = this.value.default;
|
|
@@ -134,7 +134,7 @@ let OxInputAnimationMap = class OxInputAnimationMap extends LitElement {
|
|
|
134
134
|
return;
|
|
135
135
|
const configEl = newEntry.querySelector('ox-input-animation-config');
|
|
136
136
|
const config = (configEl === null || configEl === void 0 ? void 0 : configEl.value) || {};
|
|
137
|
-
this.value = Object.assign(Object.assign({}, this.value), { [key]: config });
|
|
137
|
+
this.value = Object.assign(Object.assign({}, this.value), { [key]: { animation: config } });
|
|
138
138
|
this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }));
|
|
139
139
|
}
|
|
140
140
|
_delete(idx) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-input-animation-map.js","sourceRoot":"","sources":["../../client/data-grist/ox-input-animation-map.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Animation Map 에디터\n *\n * key-value 맵에서 value가 애니메이션 설정 객체인 경우를 위한 편집기.\n * 각 행은 key 입력 + ox-input-animation-config 폼으로 구성된다.\n *\n * value 구조 (실제 데이터):\n * {\n * \"CRITICAL\": \"{ animation: { type: 'vibration', duration: 1000, ... }, icon: { ... } }\",\n * \"WARN\": \"{ animation: { type: 'vibration', ... } }\",\n * \"default\": \"\"\n * }\n *\n * 각 entry value는 JSON5 string이며, 내부에 animation 키가 있으면 그 속성만 폼에 표시.\n * 저장 시 animation 외 다른 키(icon 등)는 보존됨.\n */\n\nimport '@material/web/icon/icon.js'\nimport './ox-input-animation-config.js'\n\nimport JSON5 from 'json5'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { keyed } from 'lit/directives/keyed.js'\n\ntype AnimationConfig = {\n type?: string\n delay?: number\n duration?: number\n interval?: number\n theta?: number\n scale?: number\n x?: number\n y?: number\n startAlpha?: number\n endAlpha?: number\n repeat?: boolean\n autoplay?: boolean\n delta?: string\n ease?: string\n}\n\ntype AnimationMap = { default?: any; [key: string]: AnimationConfig | any }\n\n// 파싱된 entry: 원본 전체 객체와 animation config를 분리 보관\ntype ParsedEntry = {\n key: string\n animation: AnimationConfig\n full: any // 원본 파싱 결과 전체 (icon 등 보존용)\n isNested: boolean // animation 키가 있는 중첩 구조 여부\n}\n\n@customElement('ox-input-animation-map')\nexport class OxInputAnimationMap extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: var(--fontsize-default, 12px);\n\n --md-icon-size: 16px;\n }\n\n .entry {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n gap: 6px;\n padding: 6px 8px;\n border: 1px solid var(--md-sys-color-outline-variant, #ddd);\n border-radius: 4px;\n background: var(--md-sys-color-surface-container, #f8f8f8);\n }\n\n .entry-key {\n flex: 0 0 80px;\n padding-top: 3px;\n }\n\n .entry-key input {\n width: 100%;\n box-sizing: border-box;\n border: 0;\n border-bottom: 1px solid transparent;\n padding: 3px 4px;\n font: var(--input-font, 12px sans-serif);\n font-weight: 600;\n color: var(--md-sys-color-on-primary-container, #333);\n background: transparent;\n }\n\n .entry-key input:focus {\n outline: none;\n border-bottom-color: var(--md-sys-color-primary, #1976d2);\n }\n\n .entry-value {\n flex: 1;\n min-width: 0;\n }\n\n .entry-action {\n flex: 0 0 auto;\n padding-top: 2px;\n }\n\n button {\n border: none;\n background: transparent;\n cursor: pointer;\n padding: 2px;\n color: var(--md-sys-color-on-surface-variant, #666);\n line-height: 0;\n }\n\n button:hover {\n color: var(--md-sys-color-primary, #1976d2);\n }\n\n .add-entry {\n opacity: 0.6;\n }\n\n .add-entry:focus-within {\n opacity: 1;\n }\n `\n\n @property({ type: Object })\n set value(v: AnimationMap) {\n const old = this._value\n this._value = this._normalize(v)\n this.requestUpdate('value', old)\n }\n get value(): AnimationMap { return this._value }\n private _value: AnimationMap = {}\n\n // 파싱된 entry 캐시 (원본 구조 보존용)\n private _parsed: ParsedEntry[] = []\n\n render() {\n this._parsed = this._parseEntries(this.value)\n\n return html`\n ${this._parsed.map(\n (item, idx) => html`\n <div class=\"entry\" data-record data-index=${idx}>\n <div class=\"entry-key\">\n <input type=\"text\" data-key .value=${item.key} placeholder=\"key\" />\n </div>\n <div class=\"entry-value\">\n <ox-input-animation-config\n .value=${item.animation}\n @change=${(e: CustomEvent) => this._onConfigChange(e, idx)}\n ></ox-input-animation-config>\n </div>\n <div class=\"entry-action\">\n <button @click=${() => this._delete(idx)} tabindex=\"-1\">\n <md-icon>remove</md-icon>\n </button>\n </div>\n </div>\n `\n )}\n ${keyed(\n Date.now(),\n html`\n <div class=\"entry add-entry\" data-record-new>\n <div class=\"entry-key\">\n <input type=\"text\" data-key value=\"\" placeholder=\"new key\" @change=${this._onNewKeyChange} />\n </div>\n <div class=\"entry-value\">\n <ox-input-animation-config .value=${{}}></ox-input-animation-config>\n </div>\n <div class=\"entry-action\">\n <button @click=${() => this._add()} tabindex=\"-1\">\n <md-icon>add</md-icon>\n </button>\n </div>\n </div>\n `\n )}\n `\n }\n\n private _onConfigChange(e: CustomEvent, idx: number) {\n e.stopPropagation()\n\n const entry = this._parsed[idx]\n if (!entry) return\n\n // 원본 구조에 animation만 교체\n const newEntryValue = entry.isNested\n ? { ...entry.full, animation: e.detail }\n : e.detail\n\n this.value = { ...this.value, [entry.key]: newEntryValue }\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _onNewKeyChange = (e: Event) => {\n e.stopPropagation()\n const input = e.target as HTMLInputElement\n if (input.value) {\n this._add()\n }\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', (e: Event) => {\n const target = e.target as HTMLElement\n const entry = target.closest('[data-record]')\n if (!entry) return\n\n // key 변경 시 rebuild\n if (target.hasAttribute('data-key')) {\n e.stopPropagation()\n this._build()\n }\n })\n }\n\n private _build() {\n const records = this.renderRoot.querySelectorAll('[data-record]')\n const newMap: AnimationMap = {}\n\n records.forEach((record, idx) => {\n const key = (record.querySelector('[data-key]') as HTMLInputElement)?.value\n if (!key) return\n\n const configEl = record.querySelector('ox-input-animation-config') as any\n const animConfig = configEl?.value || {}\n const entry = this._parsed[idx]\n\n newMap[key] = entry?.isNested\n ? { ...entry.full, animation: animConfig }\n : animConfig\n })\n\n if (this.value?.default !== undefined) {\n newMap.default = this.value.default\n }\n\n this.value = newMap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _add() {\n const newEntry = this.renderRoot.querySelector('[data-record-new]')\n if (!newEntry) return\n\n const key = (newEntry.querySelector('[data-key]') as HTMLInputElement)?.value\n if (!key) return\n\n const configEl = newEntry.querySelector('ox-input-animation-config') as any\n const config = configEl?.value || {}\n\n this.value = { ...this.value, [key]: config }\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _delete(idx: number) {\n const entry = this._parsed[idx]\n if (!entry) return\n\n const newMap = { ...this.value }\n delete newMap[entry.key]\n this.value = newMap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _parseEntries(map: AnimationMap): ParsedEntry[] {\n const arr: ParsedEntry[] = []\n for (const key in map) {\n if (key === 'default') continue\n let val = map[key]\n\n // JSON5 string → object 파싱\n if (typeof val === 'string') {\n try { val = JSON5.parse(val) } catch (e) { val = {} }\n }\n\n if (typeof val !== 'object' || val === null) {\n val = {}\n }\n\n // 중첩 구조 { animation: {...}, icon: {...} } 처리\n const isNested = 'animation' in val\n const animation = isNested ? (val.animation || {}) : val\n\n arr.push({ key, animation, full: val, isNested })\n }\n return arr\n }\n\n // 입력 value의 모든 string entry를 object로 정규화 (JSON/JSON5 호환)\n private _normalize(map: AnimationMap): AnimationMap {\n if (!map || typeof map !== 'object') return {}\n const result: AnimationMap = {}\n for (const key in map) {\n const val = map[key]\n if (typeof val === 'string' && val.trim()) {\n try { result[key] = JSON5.parse(val) } catch { result[key] = val }\n } else {\n result[key] = val\n }\n }\n return result\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-input-animation-map.js","sourceRoot":"","sources":["../../client/data-grist/ox-input-animation-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;;AAEH,OAAO,4BAA4B,CAAA;AACnC,OAAO,gCAAgC,CAAA;AAEvC,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,KAAK,CAAA;AAC3C,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AA8BxC,IAAM,mBAAmB,GAAzB,MAAM,mBAAoB,SAAQ,UAAU;IAA5C;;QAmFG,WAAM,GAAiB,EAAE,CAAA;QAEjC,2BAA2B;QACnB,YAAO,GAAkB,EAAE,CAAA;QA8D3B,oBAAe,GAAG,CAAC,CAAQ,EAAE,EAAE;YACrC,CAAC,CAAC,eAAe,EAAE,CAAA;YACnB,MAAM,KAAK,GAAG,CAAC,CAAC,MAA0B,CAAA;YAC1C,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;gBAChB,IAAI,CAAC,IAAI,EAAE,CAAA;YACb,CAAC;QACH,CAAC,CAAA;IAuGH,CAAC;IArLC,IACI,KAAK,CAAC,CAAe;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAA;QACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QAChC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,GAAG,CAAC,CAAA;IAClC,CAAC;IACD,IAAI,KAAK,KAAmB,OAAO,IAAI,CAAC,MAAM,CAAA,CAAC,CAAC;IAMhD,MAAM;QACJ,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAE7C,OAAO,IAAI,CAAA;QACP,IAAI,CAAC,OAAO,CAAC,GAAG,CAChB,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAA;sDAC2B,GAAG;;mDAEN,IAAI,CAAC,GAAG;;;;yBAIlC,IAAI,CAAC,SAAS;0BACb,CAAC,CAAc,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC;;;;+BAI3C,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;;;;;SAK7C,CACF;QACC,KAAK,CACL,IAAI,CAAC,GAAG,EAAE,EACV,IAAI,CAAA;;;mFAGuE,IAAI,CAAC,eAAe;;;kDAGrD,EAAE;;;+BAGrB,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE;;;;;SAKvC,CACF;KACF,CAAA;IACH,CAAC;IAEO,eAAe,CAAC,CAAc,EAAE,GAAW;QACjD,CAAC,CAAC,eAAe,EAAE,CAAA;QAEnB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,KAAK;YAAE,OAAM;QAElB,qDAAqD;QACrD,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ;YAClC,CAAC,iCAAM,KAAK,CAAC,IAAI,KAAE,SAAS,EAAE,CAAC,CAAC,MAAM,IACtC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAA;QAE3B,IAAI,CAAC,KAAK,mCAAQ,IAAI,CAAC,KAAK,KAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,aAAa,GAAE,CAAA;QAC1D,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACtG,CAAC;IAUD,YAAY;QACV,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAQ,EAAE,EAAE;YACtD,MAAM,MAAM,GAAG,CAAC,CAAC,MAAqB,CAAA;YACtC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;YAC7C,IAAI,CAAC,KAAK;gBAAE,OAAM;YAElB,mBAAmB;YACnB,IAAI,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;gBACpC,CAAC,CAAC,eAAe,EAAE,CAAA;gBACnB,IAAI,CAAC,MAAM,EAAE,CAAA;YACf,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAEO,MAAM;;QACZ,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAA;QACjE,MAAM,MAAM,GAAiB,EAAE,CAAA;QAE/B,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE;;YAC9B,MAAM,GAAG,GAAG,MAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAsB,0CAAE,KAAK,CAAA;YAC3E,IAAI,CAAC,GAAG;gBAAE,OAAM;YAEhB,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,2BAA2B,CAAQ,CAAA;YACzE,MAAM,UAAU,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,KAAK,KAAI,EAAE,CAAA;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAE/B,MAAM,CAAC,GAAG,CAAC,GAAG,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,QAAQ;gBAC3B,CAAC,iCAAM,KAAK,CAAC,IAAI,KAAE,SAAS,EAAE,UAAU,IACxC,CAAC,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAA;QAC/B,CAAC,CAAC,CAAA;QAEF,IAAI,CAAA,MAAA,IAAI,CAAC,KAAK,0CAAE,OAAO,MAAK,SAAS,EAAE,CAAC;YACtC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAA;QACrC,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QACnB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACtG,CAAC;IAEO,IAAI;;QACV,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,mBAAmB,CAAC,CAAA;QACnE,IAAI,CAAC,QAAQ;YAAE,OAAM;QAErB,MAAM,GAAG,GAAG,MAAC,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAsB,0CAAE,KAAK,CAAA;QAC7E,IAAI,CAAC,GAAG;YAAE,OAAM;QAEhB,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,2BAA2B,CAAQ,CAAA;QAC3E,MAAM,MAAM,GAAG,CAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,KAAK,KAAI,EAAE,CAAA;QAEpC,IAAI,CAAC,KAAK,mCAAQ,IAAI,CAAC,KAAK,KAAE,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,GAAE,CAAA;QAC5D,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACtG,CAAC;IAEO,OAAO,CAAC,GAAW;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,KAAK;YAAE,OAAM;QAElB,MAAM,MAAM,qBAAQ,IAAI,CAAC,KAAK,CAAE,CAAA;QAChC,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACxB,IAAI,CAAC,KAAK,GAAG,MAAM,CAAA;QACnB,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;IACtG,CAAC;IAEO,aAAa,CAAC,GAAiB;QACrC,MAAM,GAAG,GAAkB,EAAE,CAAA;QAC7B,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;YACtB,IAAI,GAAG,KAAK,SAAS;gBAAE,SAAQ;YAC/B,IAAI,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;YAElB,2BAA2B;YAC3B,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,IAAI,CAAC;oBAAC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBAAC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBAAC,GAAG,GAAG,EAAE,CAAA;gBAAC,CAAC;YACvD,CAAC;YAED,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC5C,GAAG,GAAG,EAAE,CAAA;YACV,CAAC;YAED,6CAA6C;YAC7C,MAAM,QAAQ,GAAG,WAAW,IAAI,GAAG,CAAA;YACnC,MAAM,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;YAExD,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAA;QACnD,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAED,yDAAyD;IACjD,UAAU,CAAC,GAAiB;QAClC,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAA;QAC9C,MAAM,MAAM,GAAiB,EAAE,CAAA;QAC/B,KAAK,MAAM,GAAG,IAAI,GAAG,EAAE,CAAC;YACtB,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAA;YACpB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC1C,IAAI,CAAC;oBAAC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;gBAAC,CAAC;gBAAC,WAAM,CAAC;oBAAC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;gBAAC,CAAC;YACpE,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAA;YACnB,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;;AA/PM,0BAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyElB,AAzEY,CAyEZ;AAED;IAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;;gDAK1B;AAjFU,mBAAmB;IAD/B,aAAa,CAAC,wBAAwB,CAAC;GAC3B,mBAAmB,CAiQ/B","sourcesContent":["/**\n * Animation Map 에디터\n *\n * key-value 맵에서 value가 애니메이션 설정 객체인 경우를 위한 편집기.\n * 각 행은 key 입력 + ox-input-animation-config 폼으로 구성된다.\n *\n * value 구조 (실제 데이터):\n * {\n * \"CRITICAL\": \"{ animation: { type: 'vibration', duration: 1000, ... }, icon: { ... } }\",\n * \"WARN\": \"{ animation: { type: 'vibration', ... } }\",\n * \"default\": \"\"\n * }\n *\n * 각 entry value는 JSON5 string이며, 내부에 animation 키가 있으면 그 속성만 폼에 표시.\n * 저장 시 animation 외 다른 키(icon 등)는 보존됨.\n */\n\nimport '@material/web/icon/icon.js'\nimport './ox-input-animation-config.js'\n\nimport JSON5 from 'json5'\nimport { css, html, LitElement } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\nimport { keyed } from 'lit/directives/keyed.js'\n\ntype AnimationConfig = {\n type?: string\n delay?: number\n duration?: number\n interval?: number\n theta?: number\n scale?: number\n x?: number\n y?: number\n startAlpha?: number\n endAlpha?: number\n repeat?: boolean\n autoplay?: boolean\n delta?: string\n ease?: string\n}\n\ntype AnimationMap = { default?: any; [key: string]: AnimationConfig | any }\n\n// 파싱된 entry: 원본 전체 객체와 animation config를 분리 보관\ntype ParsedEntry = {\n key: string\n animation: AnimationConfig\n full: any // 원본 파싱 결과 전체 (icon 등 보존용)\n isNested: boolean // animation 키가 있는 중첩 구조 여부\n}\n\n@customElement('ox-input-animation-map')\nexport class OxInputAnimationMap extends LitElement {\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n gap: 4px;\n font-size: var(--fontsize-default, 12px);\n\n --md-icon-size: 16px;\n }\n\n .entry {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n gap: 6px;\n padding: 6px 8px;\n border: 1px solid var(--md-sys-color-outline-variant, #ddd);\n border-radius: 4px;\n background: var(--md-sys-color-surface-container, #f8f8f8);\n }\n\n .entry-key {\n flex: 0 0 80px;\n padding-top: 3px;\n }\n\n .entry-key input {\n width: 100%;\n box-sizing: border-box;\n border: 0;\n border-bottom: 1px solid transparent;\n padding: 3px 4px;\n font: var(--input-font, 12px sans-serif);\n font-weight: 600;\n color: var(--md-sys-color-on-primary-container, #333);\n background: transparent;\n }\n\n .entry-key input:focus {\n outline: none;\n border-bottom-color: var(--md-sys-color-primary, #1976d2);\n }\n\n .entry-value {\n flex: 1;\n min-width: 0;\n }\n\n .entry-action {\n flex: 0 0 auto;\n padding-top: 2px;\n }\n\n button {\n border: none;\n background: transparent;\n cursor: pointer;\n padding: 2px;\n color: var(--md-sys-color-on-surface-variant, #666);\n line-height: 0;\n }\n\n button:hover {\n color: var(--md-sys-color-primary, #1976d2);\n }\n\n .add-entry {\n opacity: 0.6;\n }\n\n .add-entry:focus-within {\n opacity: 1;\n }\n `\n\n @property({ type: Object })\n set value(v: AnimationMap) {\n const old = this._value\n this._value = this._normalize(v)\n this.requestUpdate('value', old)\n }\n get value(): AnimationMap { return this._value }\n private _value: AnimationMap = {}\n\n // 파싱된 entry 캐시 (원본 구조 보존용)\n private _parsed: ParsedEntry[] = []\n\n render() {\n this._parsed = this._parseEntries(this.value)\n\n return html`\n ${this._parsed.map(\n (item, idx) => html`\n <div class=\"entry\" data-record data-index=${idx}>\n <div class=\"entry-key\">\n <input type=\"text\" data-key .value=${item.key} placeholder=\"key\" />\n </div>\n <div class=\"entry-value\">\n <ox-input-animation-config\n .value=${item.animation}\n @change=${(e: CustomEvent) => this._onConfigChange(e, idx)}\n ></ox-input-animation-config>\n </div>\n <div class=\"entry-action\">\n <button @click=${() => this._delete(idx)} tabindex=\"-1\">\n <md-icon>remove</md-icon>\n </button>\n </div>\n </div>\n `\n )}\n ${keyed(\n Date.now(),\n html`\n <div class=\"entry add-entry\" data-record-new>\n <div class=\"entry-key\">\n <input type=\"text\" data-key value=\"\" placeholder=\"new key\" @change=${this._onNewKeyChange} />\n </div>\n <div class=\"entry-value\">\n <ox-input-animation-config .value=${{}}></ox-input-animation-config>\n </div>\n <div class=\"entry-action\">\n <button @click=${() => this._add()} tabindex=\"-1\">\n <md-icon>add</md-icon>\n </button>\n </div>\n </div>\n `\n )}\n `\n }\n\n private _onConfigChange(e: CustomEvent, idx: number) {\n e.stopPropagation()\n\n const entry = this._parsed[idx]\n if (!entry) return\n\n // 항상 { animation: config } 구조로 저장 (원본에 다른 키가 있으면 보존)\n const newEntryValue = entry.isNested\n ? { ...entry.full, animation: e.detail }\n : { animation: e.detail }\n\n this.value = { ...this.value, [entry.key]: newEntryValue }\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _onNewKeyChange = (e: Event) => {\n e.stopPropagation()\n const input = e.target as HTMLInputElement\n if (input.value) {\n this._add()\n }\n }\n\n firstUpdated() {\n this.renderRoot.addEventListener('change', (e: Event) => {\n const target = e.target as HTMLElement\n const entry = target.closest('[data-record]')\n if (!entry) return\n\n // key 변경 시 rebuild\n if (target.hasAttribute('data-key')) {\n e.stopPropagation()\n this._build()\n }\n })\n }\n\n private _build() {\n const records = this.renderRoot.querySelectorAll('[data-record]')\n const newMap: AnimationMap = {}\n\n records.forEach((record, idx) => {\n const key = (record.querySelector('[data-key]') as HTMLInputElement)?.value\n if (!key) return\n\n const configEl = record.querySelector('ox-input-animation-config') as any\n const animConfig = configEl?.value || {}\n const entry = this._parsed[idx]\n\n newMap[key] = entry?.isNested\n ? { ...entry.full, animation: animConfig }\n : { animation: animConfig }\n })\n\n if (this.value?.default !== undefined) {\n newMap.default = this.value.default\n }\n\n this.value = newMap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _add() {\n const newEntry = this.renderRoot.querySelector('[data-record-new]')\n if (!newEntry) return\n\n const key = (newEntry.querySelector('[data-key]') as HTMLInputElement)?.value\n if (!key) return\n\n const configEl = newEntry.querySelector('ox-input-animation-config') as any\n const config = configEl?.value || {}\n\n this.value = { ...this.value, [key]: { animation: config } }\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _delete(idx: number) {\n const entry = this._parsed[idx]\n if (!entry) return\n\n const newMap = { ...this.value }\n delete newMap[entry.key]\n this.value = newMap\n this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: true, detail: this.value }))\n }\n\n private _parseEntries(map: AnimationMap): ParsedEntry[] {\n const arr: ParsedEntry[] = []\n for (const key in map) {\n if (key === 'default') continue\n let val = map[key]\n\n // JSON5 string → object 파싱\n if (typeof val === 'string') {\n try { val = JSON5.parse(val) } catch (e) { val = {} }\n }\n\n if (typeof val !== 'object' || val === null) {\n val = {}\n }\n\n // 중첩 구조 { animation: {...}, icon: {...} } 처리\n const isNested = 'animation' in val\n const animation = isNested ? (val.animation || {}) : val\n\n arr.push({ key, animation, full: val, isNested })\n }\n return arr\n }\n\n // 입력 value의 모든 string entry를 object로 정규화 (JSON/JSON5 호환)\n private _normalize(map: AnimationMap): AnimationMap {\n if (!map || typeof map !== 'object') return {}\n const result: AnimationMap = {}\n for (const key in map) {\n const val = map[key]\n if (typeof val === 'string' && val.trim()) {\n try { result[key] = JSON5.parse(val) } catch { result[key] = val }\n } else {\n result[key] = val\n }\n }\n return result\n }\n}\n"]}
|