{"version":3,"sources":["https://lively-kernel.org/lively4/lively4-constraints/src/components/demo/lively-simulation-state.js"],"names":["Morph","_","DEFAULT_STATE","LivelySimulationState","initialize","initializeEntries","initializeSaveDiscard","entries","get","addEventListener","handleFocusIn","handleFocusOut","initializeState","state","setStateFromJSON","save","handleSaveDiscard","discard","entriesToStateJSON","saveDiscard","handleDelete","entry","remove","isEmpty","addEmptyEntry","setState","entriesToState","clearError","message","setError","getState","selector","shadowRoot","querySelector","updateEntries","json","parse","error","status","isFocused","some","querySelectorAll","input","isChildFocused","child","doc","document","map","getKey","getValue","filteredEntries","reject","key","trim","entriesAsJson","value","join","entriesState","isEqual","keys","updateEntryValues","replaceEntries","forEach","setValue","toFixed","newEntries","toPairs","createEntry","appendChild","ensureEmpty","focus"],"mappings":"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","file":"lively-simulation-state.js","sourcesContent":["\"enable aexpr\";\n\nimport Morph from 'src/components/widgets/lively-morph.js';\nimport _ from 'src/external/lodash/lodash.js';\n\nconst DEFAULT_STATE = '{}';\n\nexport default class LivelySimulationState extends Morph {\n\n  // life cycle\n  initialize() {\n    this.initializeEntries();\n    this.initializeSaveDiscard();\n  }\n  \n  initializeEntries() {\n    const entries = this.get('#entries');\n    entries.addEventListener('focusin', () => this.handleFocusIn());\n    entries.addEventListener('focusout', () => this.handleFocusOut());\n  }\n\n  initializeState(state = DEFAULT_STATE) {\n    this.isEditing = false;\n    this.setStateFromJSON(state);\n  }\n\n  initializeSaveDiscard() {\n    const save = this.get('#save');\n    save.addEventListener('click', () => this.handleSaveDiscard(true));\n    const discard = this.get('#discard');\n    discard.addEventListener('click', () => this.handleSaveDiscard(false));\n  }\n\n  // event listener\n  handleFocusIn() {\n    if (!this.isEditing) {\n      this.isEditing = true;\n      this.checkpoint = this.entriesToStateJSON();\n      const saveDiscard = this.get('#saveDiscard');\n      saveDiscard.classList.add('show');\n    }\n  }\n\n  handleFocusOut() {\n    if (this.checkpoint === this.entriesToStateJSON()) this.handleSaveDiscard(false);\n  }\n\n  handleSaveDiscard(save) {\n    const saveDiscard = this.get('#saveDiscard');\n    saveDiscard.classList.remove('show');\n    this.isEditing = false;\n    if (save) this.save();\n    else this.discard();\n  }\n  \n  handleDelete(entry) {\n    entry.remove();\n    if (_.isEmpty(this.get('#entries').children)) this.addEmptyEntry();\n    this.get('#entries').children[0].focus();\n  }\n\n  // other\n  save() {\n    try {\n      this.setState(this.entriesToState());\n      this.clearError();\n    } catch ({ message }) {\n      this.setError(message);\n      this.get('#entries').focus();\n    }\n  }\n\n  discard() {\n    this.setStateFromJSON(this.checkpoint);\n  }\n\n  getState() {\n    return this.state;\n  }\n\n  get(selector) {\n    const { shadowRoot } = this;\n    return shadowRoot.querySelector(selector);\n  }\n\n  setState(state) {\n    this.state = state;\n    if (this.isEditing) return;\n    this.updateEntries();\n  }\n\n  setStateFromJSON(json) {\n    const state = JSON.parse(json);\n    this.setState(state);\n  }\n\n  setError(error) {\n    const status = this.get('#status');\n    status.innerText = error;\n    status.classList.add('error');\n  }\n\n  clearError() {\n    const status = this.get('#status');\n    status.innerText = '';\n    status.classList.remove('error');\n  }\n\n  isFocused() {\n    const { shadowRoot } = this;\n    return _.some(shadowRoot.querySelectorAll('input'), input => this.isChildFocused(input));\n  }\n\n  isChildFocused(child, doc = document) {\n    if (doc.activeElement === child) return true;\n    if (doc.activeElement && doc.activeElement.shadowRoot)\n\t\t\treturn this.isChildFocused(child, doc.activeElement.shadowRoot)\n    return false;\n  }\n  \n  entriesToState() {\n    return JSON.parse(this.entriesToStateJSON());\n  }\n  \n  entriesToStateJSON() {\n    const entries = _.map([...this.get('#entries').children], entry => [entry.getKey(), entry.getValue()]);\n    const filteredEntries = _.reject(entries, ([ key ]) => _.isEmpty(key.trim()));\n    const entriesAsJson = _.map(filteredEntries, ([ key, value ]) => `\"${key}\": ${isNaN(value) ? `\"${value}\"` : value}`);\n    return `{\n      ${\n        _.join(entriesAsJson, ',\\n')\n      }\n    }`;\n  }\n  \n  updateEntries() {\n    const { state } = this;\n    const entriesState = this.entriesToState();\n    if (_.isEqual(state, entriesState)) return;\n    if (_.isEqual(_.keys(state), _.keys(entriesState))) this.updateEntryValues();\n    else this.replaceEntries();\n  }\n  \n  updateEntryValues() {\n    const { state } = this;\n    if (_.isEqual(state, {})) return this.addEmptyEntry();\n    const entries = _.reject([...this.get('#entries').children], entry => _.isEmpty(entry.getKey().trim()));\n    _.forEach(entries, entry => {\n      const value = state[entry.getKey()];\n      entry.setValue(isNaN(value) ? value : parseFloat(value.toFixed(3)));\n    });\n  }\n  \n  replaceEntries() {\n    const { state } = this;\n    const entries = this.get('#entries');\n    entries.innerHTML = ''; // no diffing, just plain remove all + add\n    const newEntries = _.map(_.toPairs(state), ([key, value]) => this.createEntry(key, isNaN(value) ? value : parseFloat(value.toFixed(3))));\n    _.forEach(newEntries, (entry) => entries.appendChild(entry));\n    this.addEmptyEntry();\n  }\n  \n  addEmptyEntry() {\n    const entries = this.get('#entries');\n    entries.appendChild(this.createEntry('', ''));\n  }\n  \n  ensureEmpty(entry) {\n    const entries = [...this.get('#entries').children];\n    if (!_.some(entries, entry => _.isEmpty(entry.getKey().trim()) && _.isEmpty(entry.getValue().trim())))\n      this.addEmptyEntry();\n    entry.focus();\n  }\n  \n  createEntry(key, value) {\n    const entry = (\n      <div class='entry'>\n        <input value={String(key)} placeholder='Key' />\n        <input value={String(value)} placeholder='Value' />\n        <i class=\"fa fa-times\"></i>\n      </div>\n    );\n    entry.children[0].addEventListener('input', () => this.ensureEmpty(entry));\n    entry.children[1].addEventListener('input', () => this.ensureEmpty(entry));\n    entry.children[2].addEventListener('mousedown', () => this.handleDelete(entry));\n    entry.getKey = () => entry.children[0].value;\n    entry.getValue = () => entry.children[1].value;\n    entry.setValue = (value) => entry.children[1].value = value;\n    return entry;\n  }\n}\n"]}