@panoramax/web-viewer 4.1.0-develop-55fdf56c → 4.1.0-develop-22cdb9e7

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.
@@ -1 +1 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><title>Panoramax Widgets</title><style>body{font-family:sans-serif;padding-bottom:100px}h1,h2,nav,p{text-align:center}.test-bench{display:flex;width:100%;max-width:600px;margin:7px auto;justify-content:space-between;align-items:center}.test-bench h3{margin:0}hr.test-sep{width:100%;max-width:600px}</style><script defer="defer" src="index.js"></script><link href="index.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><h1>Panoramax widgets</h1><p>Test page for common Panoramax viewer widgets</p><nav><a href="#button">Button</a> <a href="#link-button">Link Button</a> <a href="#copy-button">Copy button</a> <a href="#button-group">Button Group</a> <a href="#5stars">5-stars grade</a> <a href="#quality-score">Quality Score</a> <a href="#search-bar">Search bar</a> <a href="#progress-bar">Progress bar</a> <a href="#tabs">Tabs</a> <a href="#semantics-editor">Semantics Editor</a></nav><h2 id="button">Button</h2><div class="test-bench"><h3>Text + click</h3><pnx-button onclick='alert("Stuff")'>Click to do stuff</pnx-button></div><div class="test-bench"><h3>Icon</h3><pnx-button>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Active</h3><pnx-button active="true">Settings</pnx-button></div><div class="test-bench"><h3>CSS override</h3><div style="width:50%;display:flex;gap:5px;max-width:300px"><pnx-button style="width:50%">⚙️ Settings</pnx-button><pnx-button style="width:50%">🖨️ Print</pnx-button></div></div><hr class="test-sep"/><div class="test-bench"><h3>Full</h3><pnx-button kind="full">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Full active</h3><pnx-button kind="full" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Full L</h3><pnx-button kind="full" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Full XXL</h3><pnx-button kind="full" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Outline</h3><pnx-button kind="outline">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Outline active</h3><pnx-button kind="outline" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Outline L</h3><pnx-button kind="outline" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Outline XXL</h3><pnx-button kind="outline" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Inline</h3><pnx-button kind="inline">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Inline active</h3><pnx-button kind="inline" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Inline L</h3><pnx-button kind="inline" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Inline XXL</h3><pnx-button kind="inline" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Superinline</h3><pnx-button kind="superinline">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Superinline active</h3><pnx-button kind="superinline" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Superinline L</h3><pnx-button kind="superinline" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Superinline XXL</h3><pnx-button kind="superinline" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Flat</h3><pnx-button kind="flat">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Flat active</h3><pnx-button kind="flat" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Flat L</h3><pnx-button kind="flat" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Flat XXL</h3><pnx-button kind="flat" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Superflat</h3><pnx-button kind="superflat">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Superflat active</h3><pnx-button kind="superflat" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Superflat L</h3><pnx-button kind="superflat" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Superflat XXL</h3><pnx-button kind="superflat" size="xxl">⚙️</pnx-button></div><h2 id="link-button">Link Button</h2><div class="test-bench"><h3>None set</h3><pnx-link-button>Click for nothing</pnx-link-button></div><div class="test-bench"><h3>All set</h3><pnx-link-button target="_blank" href="https://panoramax.fr" title="Do stuff">Click to do stuff</pnx-link-button></div><h2 id="copy-button">Copy button</h2><div class="test-bench"><h3>Default + text</h3><pnx-copy-button text="copypasta1"></pnx-copy-button></div><div class="test-bench"><h3>Custom + text</h3><pnx-copy-button text="copypasta2">🌐 Share URL</pnx-copy-button></div><div class="test-bench"><h3>Default + input</h3><div style="display:flex;gap:5px;align-items:center"><input value="copypasta3" id="copy-input-1"/><pnx-copy-button input="copy-input-1"></pnx-copy-button></div></div><h2 id="button-group">Button Group</h2><div class="test-bench"><h3>Full Row x2</h3><div><pnx-button-group dir="row"><pnx-button>☹️</pnx-button><pnx-button>🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Row x3</h3><div><pnx-button-group dir="row"><pnx-button>☹️</pnx-button><pnx-button>😐</pnx-button><pnx-button>🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Row mixed</h3><div><pnx-button-group dir="row"><pnx-button>☹️</pnx-button><pnx-link-button>😐</pnx-link-button><pnx-copy-button>🙂</pnx-copy-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Column x2</h3><div><pnx-button-group dir="column"><pnx-button>☹️</pnx-button><pnx-button>🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Column x3</h3><div><pnx-button-group dir="column"><pnx-button>☹️</pnx-button><pnx-button>😐</pnx-button><pnx-button>🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Column mixed</h3><div><pnx-button-group dir="column"><pnx-button>☹️</pnx-button><pnx-link-button>😐</pnx-link-button><pnx-copy-button>🙂</pnx-copy-button></pnx-button-group></div></div><hr class="test-sep"/><div class="test-bench"><h3>Outline Row x2</h3><div><pnx-button-group dir="row"><pnx-button kind="outline">☹️</pnx-button><pnx-button kind="outline">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Outline Row x3</h3><div><pnx-button-group dir="row"><pnx-button kind="outline">☹️</pnx-button><pnx-button kind="outline">😐</pnx-button><pnx-button kind="outline">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Outline Column x2</h3><div><pnx-button-group dir="column"><pnx-button kind="outline">☹️</pnx-button><pnx-button kind="outline">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Outline Column x3</h3><div><pnx-button-group dir="column"><pnx-button kind="outline">☹️</pnx-button><pnx-button kind="outline">😐</pnx-button><pnx-button kind="outline">🙂</pnx-button></pnx-button-group></div></div><hr class="test-sep"/><div class="test-bench"><h3>Flat Row x2</h3><div><pnx-button-group dir="row"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Flat Row x3</h3><div><pnx-button-group dir="row"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">😐</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Flat Column x2</h3><div><pnx-button-group dir="column"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Flat Column x3</h3><div><pnx-button-group dir="column"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">😐</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><hr class="test-sep"/><div class="test-bench"><h3>Row XL</h3><div><pnx-button-group size="xl" dir="row"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">😐</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Column XL</h3><div><pnx-button-group size="xl" dir="column"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">😐</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><h2 id="5stars">5-stars grade</h2><div class="test-bench"><h3>With a grade</h3><pnx-grade stars="5"/></div><div class="test-bench"><h3>Without a grade</h3><pnx-grade/></div><h2 id="quality-score">Quality Score</h2><div class="test-bench"><h3>Classic no grade</h3><pnx-quality-score/></div><div class="test-bench"><h3>Classic 1/5</h3><pnx-quality-score grade="1"/></div><div class="test-bench"><h3>Classic 2/5</h3><pnx-quality-score grade="2"/></div><div class="test-bench"><h3>Classic 3/5</h3><pnx-quality-score grade="3"/></div><div class="test-bench"><h3>Classic 4/5</h3><pnx-quality-score grade="4"/></div><div class="test-bench"><h3>Classic 5/5</h3><pnx-quality-score grade="5"/></div><hr class="test-sep"/><div class="test-bench"><h3>Input</h3><pnx-quality-score input="qs"/></div><div class="test-bench"><h3>Input 1/5</h3><pnx-quality-score input="qs" grade="1"/></div><div class="test-bench"><h3>Input 2/5</h3><pnx-quality-score input="qs" grade="2"/></div><div class="test-bench"><h3>Input 3/5</h3><pnx-quality-score input="qs" grade="3"/></div><div class="test-bench"><h3>Input 4/5</h3><pnx-quality-score input="qs" grade="4"/></div><div class="test-bench"><h3>Input 5/5</h3><pnx-quality-score input="qs" grade="5"/></div><div class="test-bench"><h3>Input many</h3><pnx-quality-score input="qs" grade="1,3,5"/></div><h2 id="search-bar">Search bar</h2><div class="test-bench"><h3>Simple</h3><pnx-search-bar placeholder="Start your search"></pnx-search-bar></div><div class="test-bench"><h3>With pre</h3><pnx-search-bar placeholder="Look for a place"><span slot="pre">🗺️</span></pnx-search-bar></div><div class="test-bench"><h3>Reduced</h3><pnx-search-bar reduceable reduced placeholder="Look for a place"></pnx-search-bar></div><hr class="test-sep"/><div class="test-bench"><h3>Size md full</h3><pnx-search-bar size="md" placeholder="Look for a place"><span slot="pre">🗺️</span></pnx-search-bar></div><div class="test-bench"><h3>Size md reduced</h3><pnx-search-bar size="md" reduceable reduced placeholder="Look for a place"></pnx-search-bar></div><div class="test-bench"><h3>Size xxl full</h3><pnx-search-bar size="xxl" placeholder="Look for a place"><span slot="pre">🗺️</span></pnx-search-bar></div><div class="test-bench"><h3>Size xxl reduced</h3><pnx-search-bar size="xxl" reduceable reduced placeholder="Look for a place"></pnx-search-bar></div><h2 id="progress-bar">Progress bar</h2><div class="test-bench"><h3>Half</h3><pnx-progress-bar value="42"></pnx-progress-bar></div><div class="test-bench"><h3>Indeterminate</h3><pnx-progress-bar></pnx-progress-bar></div><div class="test-bench"><h3>Full</h3><pnx-progress-bar value="100"></pnx-progress-bar></div><h2 id="tabs">Tabs</h2><div class="test-bench"><h3>Many</h3><pnx-tabs><h4 slot="title">Tab 1</h4><div slot="content">Tab 1 content</div><h4 slot="title">Tab 2</h4><div slot="content">Tab 2 content</div><h4 slot="title">Tab 3</h4><div slot="content">Tab 3 content</div></pnx-tabs></div><h2 id="semantics-editor">Semantics editor</h2><script>window.addEventListener("load",(()=>{const e=document.getElementsByTagName("pnx-semantics-editor");for(let t=0;t<e.length;t++){const n=e[t];n.nextSibling;n.addEventListener("change",(e=>{console.log("Semantics change > evt =",e.detail,"| attr =",n.getAttribute("semantics"))}))}}))</script><div class="test-bench"><h3>Empty</h3><pnx-semantics-editor _t='{"pnx": {"semantics_editor_error": "The syntax is invalid. Your tags may look like:\nkey=value\nprefix|key=value\nprefix|key[qualif_key=qualif_val]=value"}}'></pnx-semantics-editor></div><div class="test-bench"><h3>Filled</h3><pnx-semantics-editor semantics="[{key: 'osm|traffic_sign', value: 'FR:A14b'}]"></pnx-semantics-editor></div><div class="test-bench"><h3>Many rows</h3><pnx-semantics-editor rows="5" semantics="[{key: 'osm|traffic_sign', value: 'FR:A14b'}]"></pnx-semantics-editor></div><div class="test-bench"><h3>Custom style</h3><style>#pnx-sem-ed3::part(text){color:#00f}</style><pnx-semantics-editor id="pnx-sem-ed3" semantics="[{key: 'osm|traffic_sign', value: 'FR:A14b'}]"></pnx-semantics-editor></div></body></html>
1
+ <!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><title>Panoramax Widgets</title><style>body{font-family:sans-serif;padding-bottom:100px}h1,h2,nav,p{text-align:center}.test-bench{display:flex;width:100%;max-width:600px;margin:7px auto;justify-content:space-between;align-items:center}.test-bench h3{margin:0}hr.test-sep{width:100%;max-width:600px}</style><script defer="defer" src="index.js"></script><link href="index.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><h1>Panoramax widgets</h1><p>Test page for common Panoramax viewer widgets</p><nav><a href="#button">Button</a> <a href="#link-button">Link Button</a> <a href="#copy-button">Copy button</a> <a href="#button-group">Button Group</a> <a href="#5stars">5-stars grade</a> <a href="#quality-score">Quality Score</a> <a href="#search-bar">Search bar</a> <a href="#progress-bar">Progress bar</a> <a href="#tabs">Tabs</a> <a href="#semantics-editor">Semantics Editor</a></nav><h2 id="button">Button</h2><div class="test-bench"><h3>Text + click</h3><pnx-button onclick='alert("Stuff")'>Click to do stuff</pnx-button></div><div class="test-bench"><h3>Icon</h3><pnx-button>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Active</h3><pnx-button active="true">Settings</pnx-button></div><div class="test-bench"><h3>CSS override</h3><div style="width:50%;display:flex;gap:5px;max-width:300px"><pnx-button style="width:50%">⚙️ Settings</pnx-button><pnx-button style="width:50%">🖨️ Print</pnx-button></div></div><hr class="test-sep"/><div class="test-bench"><h3>Full</h3><pnx-button kind="full">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Full active</h3><pnx-button kind="full" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Full L</h3><pnx-button kind="full" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Full XXL</h3><pnx-button kind="full" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Outline</h3><pnx-button kind="outline">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Outline active</h3><pnx-button kind="outline" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Outline L</h3><pnx-button kind="outline" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Outline XXL</h3><pnx-button kind="outline" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Inline</h3><pnx-button kind="inline">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Inline active</h3><pnx-button kind="inline" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Inline L</h3><pnx-button kind="inline" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Inline XXL</h3><pnx-button kind="inline" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Superinline</h3><pnx-button kind="superinline">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Superinline active</h3><pnx-button kind="superinline" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Superinline L</h3><pnx-button kind="superinline" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Superinline XXL</h3><pnx-button kind="superinline" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Flat</h3><pnx-button kind="flat">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Flat active</h3><pnx-button kind="flat" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Flat L</h3><pnx-button kind="flat" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Flat XXL</h3><pnx-button kind="flat" size="xxl">⚙️</pnx-button></div><div class="test-bench"><h3>Superflat</h3><pnx-button kind="superflat">⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Superflat active</h3><pnx-button kind="superflat" active>⚙️ Settings</pnx-button></div><div class="test-bench"><h3>Superflat L</h3><pnx-button kind="superflat" size="l">⚙️</pnx-button></div><div class="test-bench"><h3>Superflat XXL</h3><pnx-button kind="superflat" size="xxl">⚙️</pnx-button></div><h2 id="link-button">Link Button</h2><div class="test-bench"><h3>None set</h3><pnx-link-button>Click for nothing</pnx-link-button></div><div class="test-bench"><h3>All set</h3><pnx-link-button target="_blank" href="https://panoramax.fr" title="Do stuff">Click to do stuff</pnx-link-button></div><h2 id="copy-button">Copy button</h2><div class="test-bench"><h3>Default + text</h3><pnx-copy-button text="copypasta1"></pnx-copy-button></div><div class="test-bench"><h3>Custom + text</h3><pnx-copy-button text="copypasta2">🌐 Share URL</pnx-copy-button></div><div class="test-bench"><h3>Default + input</h3><div style="display:flex;gap:5px;align-items:center"><input value="copypasta3" id="copy-input-1"/><pnx-copy-button input="copy-input-1"></pnx-copy-button></div></div><h2 id="button-group">Button Group</h2><div class="test-bench"><h3>Full Row x2</h3><div><pnx-button-group dir="row"><pnx-button>☹️</pnx-button><pnx-button>🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Row x3</h3><div><pnx-button-group dir="row"><pnx-button>☹️</pnx-button><pnx-button>😐</pnx-button><pnx-button>🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Row mixed</h3><div><pnx-button-group dir="row"><pnx-button>☹️</pnx-button><pnx-link-button>😐</pnx-link-button><pnx-copy-button>🙂</pnx-copy-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Column x2</h3><div><pnx-button-group dir="column"><pnx-button>☹️</pnx-button><pnx-button>🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Column x3</h3><div><pnx-button-group dir="column"><pnx-button>☹️</pnx-button><pnx-button>😐</pnx-button><pnx-button>🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Full Column mixed</h3><div><pnx-button-group dir="column"><pnx-button>☹️</pnx-button><pnx-link-button>😐</pnx-link-button><pnx-copy-button>🙂</pnx-copy-button></pnx-button-group></div></div><hr class="test-sep"/><div class="test-bench"><h3>Outline Row x2</h3><div><pnx-button-group dir="row"><pnx-button kind="outline">☹️</pnx-button><pnx-button kind="outline">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Outline Row x3</h3><div><pnx-button-group dir="row"><pnx-button kind="outline">☹️</pnx-button><pnx-button kind="outline">😐</pnx-button><pnx-button kind="outline">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Outline Column x2</h3><div><pnx-button-group dir="column"><pnx-button kind="outline">☹️</pnx-button><pnx-button kind="outline">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Outline Column x3</h3><div><pnx-button-group dir="column"><pnx-button kind="outline">☹️</pnx-button><pnx-button kind="outline">😐</pnx-button><pnx-button kind="outline">🙂</pnx-button></pnx-button-group></div></div><hr class="test-sep"/><div class="test-bench"><h3>Flat Row x2</h3><div><pnx-button-group dir="row"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Flat Row x3</h3><div><pnx-button-group dir="row"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">😐</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Flat Column x2</h3><div><pnx-button-group dir="column"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Flat Column x3</h3><div><pnx-button-group dir="column"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">😐</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><hr class="test-sep"/><div class="test-bench"><h3>Row XL</h3><div><pnx-button-group size="xl" dir="row"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">😐</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><div class="test-bench"><h3>Column XL</h3><div><pnx-button-group size="xl" dir="column"><pnx-button kind="flat">☹️</pnx-button><pnx-button kind="flat">😐</pnx-button><pnx-button kind="flat">🙂</pnx-button></pnx-button-group></div></div><h2 id="5stars">5-stars grade</h2><div class="test-bench"><h3>With a grade</h3><pnx-grade stars="5"/></div><div class="test-bench"><h3>Without a grade</h3><pnx-grade/></div><h2 id="quality-score">Quality Score</h2><div class="test-bench"><h3>Classic no grade</h3><pnx-quality-score/></div><div class="test-bench"><h3>Classic 1/5</h3><pnx-quality-score grade="1"/></div><div class="test-bench"><h3>Classic 2/5</h3><pnx-quality-score grade="2"/></div><div class="test-bench"><h3>Classic 3/5</h3><pnx-quality-score grade="3"/></div><div class="test-bench"><h3>Classic 4/5</h3><pnx-quality-score grade="4"/></div><div class="test-bench"><h3>Classic 5/5</h3><pnx-quality-score grade="5"/></div><hr class="test-sep"/><div class="test-bench"><h3>Input</h3><pnx-quality-score input="qs"/></div><div class="test-bench"><h3>Input 1/5</h3><pnx-quality-score input="qs" grade="1"/></div><div class="test-bench"><h3>Input 2/5</h3><pnx-quality-score input="qs" grade="2"/></div><div class="test-bench"><h3>Input 3/5</h3><pnx-quality-score input="qs" grade="3"/></div><div class="test-bench"><h3>Input 4/5</h3><pnx-quality-score input="qs" grade="4"/></div><div class="test-bench"><h3>Input 5/5</h3><pnx-quality-score input="qs" grade="5"/></div><div class="test-bench"><h3>Input many</h3><pnx-quality-score input="qs" grade="1,3,5"/></div><h2 id="search-bar">Search bar</h2><div class="test-bench"><h3>Simple</h3><pnx-search-bar placeholder="Start your search"></pnx-search-bar></div><div class="test-bench"><h3>With pre</h3><pnx-search-bar placeholder="Look for a place"><span slot="pre">🗺️</span></pnx-search-bar></div><div class="test-bench"><h3>Reduced</h3><pnx-search-bar reduceable reduced placeholder="Look for a place"></pnx-search-bar></div><hr class="test-sep"/><div class="test-bench"><h3>Size md full</h3><pnx-search-bar size="md" placeholder="Look for a place"><span slot="pre">🗺️</span></pnx-search-bar></div><div class="test-bench"><h3>Size md reduced</h3><pnx-search-bar size="md" reduceable reduced placeholder="Look for a place"></pnx-search-bar></div><div class="test-bench"><h3>Size xxl full</h3><pnx-search-bar size="xxl" placeholder="Look for a place"><span slot="pre">🗺️</span></pnx-search-bar></div><div class="test-bench"><h3>Size xxl reduced</h3><pnx-search-bar size="xxl" reduceable reduced placeholder="Look for a place"></pnx-search-bar></div><h2 id="progress-bar">Progress bar</h2><div class="test-bench"><h3>Half</h3><pnx-progress-bar value="42"></pnx-progress-bar></div><div class="test-bench"><h3>Indeterminate</h3><pnx-progress-bar></pnx-progress-bar></div><div class="test-bench"><h3>Full</h3><pnx-progress-bar value="100"></pnx-progress-bar></div><h2 id="tabs">Tabs</h2><div class="test-bench"><h3>Many</h3><pnx-tabs><h4 slot="title">Tab 1</h4><div slot="content">Tab 1 content</div><h4 slot="title">Tab 2</h4><div slot="content">Tab 2 content</div><h4 slot="title">Tab 3</h4><div slot="content">Tab 3 content</div></pnx-tabs></div><h2 id="semantics-editor">Semantics editor</h2><script>window.addEventListener("load",(()=>{const e=document.getElementsByTagName("pnx-semantics-editor");for(let t=0;t<e.length;t++){const n=e[t];n.nextSibling;n.addEventListener("change",(e=>{console.log("Semantics change > evt =",e.detail,"| attr =",n.getAttribute("semantics"))}))}}))</script><div class="test-bench"><h3>Empty</h3><pnx-semantics-editor _t='{"pnx": {"semantics_editor_error": "La syntaxe est invalide. Vos attributs doivent avoir cette forme:\nclé=valeur\npréfixe|clé=valeur\npréfixe|clé[qualif_clé=qualif_val]=valeur\n\nLongueur max des clés : 256 caractères, max des valeurs 2048 caractères.","semantics_editor_example": "clé=valeur\npréfixe|clé=valeur"}}'></pnx-semantics-editor></div><div class="test-bench"><h3>Filled</h3><pnx-semantics-editor semantics="[{key: 'osm|traffic_sign', value: 'FR:A14b'}]"></pnx-semantics-editor></div><div class="test-bench"><h3>Many rows</h3><pnx-semantics-editor rows="5" semantics="[{key: 'osm|traffic_sign', value: 'FR:A14b'}]"></pnx-semantics-editor></div><div class="test-bench"><h3>Custom style</h3><style>#pnx-sem-ed3::part(text){color:#00f}</style><pnx-semantics-editor id="pnx-sem-ed3" semantics="[{key: 'osm|traffic_sign', value: 'FR:A14b'}]"></pnx-semantics-editor></div></body></html>
@@ -0,0 +1,15 @@
1
+ <a name="Panoramax.components.menus.SemanticsMetadata"></a>
2
+
3
+ ## Panoramax.components.menus.SemanticsMetadata ⇐ <code>[lit.LitElement](https://lit.dev/docs/api/LitElement/)</code>
4
+ **Kind**: static class of <code>Panoramax.components.menus</code>
5
+ **Extends**: <code>[lit.LitElement](https://lit.dev/docs/api/LitElement/)</code>
6
+ **Element**: pnx-semantics-metadata
7
+ <a name="new_Panoramax.components.menus.SemanticsMetadata_new"></a>
8
+
9
+ ### new SemanticsMetadata()
10
+ Semantics metadata displays detailed info about semantic attributes of a single picture.
11
+
12
+ **Example**
13
+ ```html
14
+ <pnx-semantics-metadata ._parent=${viewer}></pnx-semantics-metadata>
15
+ ```
@@ -11,6 +11,7 @@
11
11
  * [.properties](#Panoramax.components.ui.SemanticsEditor+properties) : <code>Object</code>
12
12
  * [.getDiff()](#Panoramax.components.ui.SemanticsEditor+getDiff) ⇒ <code>Array.&lt;object&gt;</code>
13
13
  * [.checkValidity()](#Panoramax.components.ui.SemanticsEditor+checkValidity) ⇒ <code>boolean</code>
14
+ * [.reset([baseSemantics])](#Panoramax.components.ui.SemanticsEditor+reset)
14
15
  * ["change"](#Panoramax.components.ui.SemanticsEditor+event_change)
15
16
 
16
17
  <a name="new_Panoramax.components.ui.SemanticsEditor_new"></a>
@@ -70,6 +71,17 @@ Check if input is having a valid value.
70
71
 
71
72
  **Kind**: instance method of [<code>SemanticsEditor</code>](#Panoramax.components.ui.SemanticsEditor)
72
73
  **Returns**: <code>boolean</code> - True if it's valid
74
+ <a name="Panoramax.components.ui.SemanticsEditor+reset"></a>
75
+
76
+ ### semanticsEditor.reset([baseSemantics])
77
+ Forces Editor to goes back to its empty, initial state.
78
+
79
+ **Kind**: instance method of [<code>SemanticsEditor</code>](#Panoramax.components.ui.SemanticsEditor)
80
+
81
+ | Param | Type | Default | Description |
82
+ | --- | --- | --- | --- |
83
+ | [baseSemantics] | <code>object</code> | <code></code> | Initial existing semantics you want to show in editor. This is useful for getting a diff of only new semantic entries. Leave empty if no tags pre-exist. |
84
+
73
85
  <a name="Panoramax.components.ui.SemanticsEditor+event_change"></a>
74
86
 
75
87
  ### "change"
@@ -25,6 +25,7 @@
25
25
  * [.searchUsers(query)](#Panoramax.utils.API+searchUsers) ⇒ <code>Promise</code>
26
26
  * [.getUserName(userId)](#Panoramax.utils.API+getUserName) ⇒ <code>Promise</code>
27
27
  * [.sendReport(data)](#Panoramax.utils.API+sendReport) ⇒ <code>Promise</code>
28
+ * [.sendPictureSemantics(picMeta, semanticsDiff)](#Panoramax.utils.API+sendPictureSemantics) ⇒ <code>Promise</code>
28
29
  * ["broken"](#Panoramax.utils.API+event_broken)
29
30
  * ["ready"](#Panoramax.utils.API+event_ready)
30
31
  * _static_
@@ -284,6 +285,19 @@ Send a report to API
284
285
  | --- | --- | --- |
285
286
  | data | <code>object</code> | The input form data |
286
287
 
288
+ <a name="Panoramax.utils.API+sendPictureSemantics"></a>
289
+
290
+ ### api.sendPictureSemantics(picMeta, semanticsDiff) ⇒ <code>Promise</code>
291
+ Send picture semantics change to origin API.
292
+
293
+ **Kind**: instance method of [<code>API</code>](#Panoramax.utils.API)
294
+ **Fulfil**: <code>object</code> The JSON API response
295
+
296
+ | Param | Type | Description |
297
+ | --- | --- | --- |
298
+ | picMeta | <code>object</code> | The picture metadata |
299
+ | semanticsDiff | <code>object</code> | The difference in semantics compared to original data |
300
+
287
301
  <a name="Panoramax.utils.API+event_broken"></a>
288
302
 
289
303
  ### "broken"
package/docs/reference.md CHANGED
@@ -36,6 +36,7 @@ All-in-one, ready-to-use menus for complex operations. Note that they don't embe
36
36
  - [PlayerOptions](./reference/components/menus/PlayerOptions.md) : speed and constrast settings for play sequence feature.
37
37
  - [QualityScoreDoc](./reference/components/menus/QualityScoreDoc.md) : details about quality score computation.
38
38
  - [ReportForm](./reference/components/menus/ReportForm.md) : picture issue reporting form.
39
+ - [SemanticsMetadata](./reference/components/menus/SemanticsMetadata.md) : display full details about a picture semantics.
39
40
  - [ShareMenu](./reference/components/menus/ShareMenu.md) : links and iframe sharing.
40
41
 
41
42
  ## `components.ui`
@@ -83,4 +84,5 @@ General helpers outside of single component scope:
83
84
 
84
85
  - [API](./reference/utils/API.md) : the Panoramax API helper (many get & post HTTP helpers).
85
86
  - [InitParameters](./reference/utils/InitParameters.md) : helper for merging URL and component parameters.
87
+ - [PresetsManager](./reference/utils/PresetsManager.md) : the semantics attributes presets manager.
86
88
  - [URLHandler](./reference/utils/URLHandler.md) : the window URL manager (changes query part).
package/mkdocs.yml CHANGED
@@ -76,6 +76,7 @@ nav:
76
76
  - PlayerOptions: 'reference/components/menus/PlayerOptions.md'
77
77
  - QualityScoreDoc: 'reference/components/menus/QualityScoreDoc.md'
78
78
  - ReportForm: 'reference/components/menus/ReportForm.md'
79
+ - SemanticsMetadata: 'reference/components/menus/SemanticsMetadata.md'
79
80
  - ShareMenu: 'reference/components/menus/ShareMenu.md'
80
81
  - ui:
81
82
  - widgets:
@@ -110,4 +111,5 @@ nav:
110
111
  - utils:
111
112
  - API: 'reference/utils/API.md'
112
113
  - InitParameters: 'reference/utils/InitParameters.md'
114
+ - PresetsManager: 'reference/utils/PresetsManager.md'
113
115
  - URLHandler: 'reference/utils/URLHandler.md'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@panoramax/web-viewer",
3
- "version": "4.1.0-develop-55fdf56c",
3
+ "version": "4.1.0-develop-22cdb9e7",
4
4
  "description": "Panoramax web viewer for geolocated pictures",
5
5
  "main": "build/index.js",
6
6
  "author": "Panoramax team",
@@ -319,7 +319,7 @@
319
319
  </script>
320
320
  <div class="test-bench">
321
321
  <h3>Empty</h3>
322
- <pnx-semantics-editor _t='{"pnx": {"semantics_editor_error": "The syntax is invalid. Your tags may look like:\nkey=value\nprefix|key=value\nprefix|key[qualif_key=qualif_val]=value"}}'></pnx-semantics-editor>
322
+ <pnx-semantics-editor _t='{"pnx": {"semantics_editor_error": "La syntaxe est invalide. Vos attributs doivent avoir cette forme:\nclé=valeur\npréfixe|clé=valeur\npréfixe|clé[qualif_clé=qualif_val]=valeur\n\nLongueur max des clés : 256 caractères, max des valeurs 2048 caractères.","semantics_editor_example": "clé=valeur\npréfixe|clé=valeur"}}'></pnx-semantics-editor>
323
323
  </div>
324
324
  <div class="test-bench">
325
325
  <h3>Filled</h3>
@@ -345,7 +345,11 @@ export default class Basic extends LitElement {
345
345
  else if(typeof value === "object" || Array.isArray(value)) { return value; }
346
346
  else { return JSON5.parse(value); }
347
347
  },
348
- toAttribute: (value) => JSON.stringify(value)
348
+ toAttribute: (value) => {
349
+ if(value === null || value === "") { return ""; }
350
+ else if(typeof value === "string") { return value; }
351
+ else { return JSON5.stringify(value); }
352
+ }
349
353
  };
350
354
  }
351
355
  }
@@ -9,12 +9,10 @@ import { faImages } from "@fortawesome/free-solid-svg-icons/faImages";
9
9
  import { faScroll } from "@fortawesome/free-solid-svg-icons/faScroll";
10
10
  import { faQuestion } from "@fortawesome/free-solid-svg-icons/faQuestion";
11
11
  import { faInfoCircle } from "@fortawesome/free-solid-svg-icons/faInfoCircle";
12
- import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
13
- import { faChevronUp } from "@fortawesome/free-solid-svg-icons/faChevronUp";
14
12
  import { faTags } from "@fortawesome/free-solid-svg-icons/faTags";
15
- import { faSvg, titles, textarea, hidden } from "../styles";
13
+ import { faSvg, titles, textarea, hidden, dataBlocks } from "../styles";
16
14
  import { createWebComp } from "../../utils/widgets";
17
- import { getGPSPrecision, getHashTags } from "../../utils/picture";
15
+ import { getGPSPrecision } from "../../utils/picture";
18
16
  import { PanoramaxMetaCatalogURL } from "../../utils/services";
19
17
  import {
20
18
  getGrade, QUALITYSCORE_GPS_VALUES, QUALITYSCORE_RES_360_VALUES,
@@ -35,30 +33,14 @@ const missing = () => fa(faQuestion, {styles: {height: "16px"}});
35
33
  */
36
34
  export default class PictureMetadata extends LitElement {
37
35
  /** @private */
38
- static styles = [ faSvg, titles, textarea, hidden, css`
36
+ static styles = [ faSvg, titles, textarea, hidden, dataBlocks, css`
39
37
  div[slot="content"] {
40
38
  padding: 5px 10px;
41
39
  background-color: #ededed;
42
40
  }
43
41
 
44
- /* Small data blocks */
45
42
  .data-block {
46
- display: inline-block;
47
43
  min-width: 50%;
48
- margin: 8px 0;
49
- box-sizing: border-box;
50
- vertical-align: top;
51
- }
52
- .data-block h5 {
53
- font-size: 0.8em;
54
- font-weight: 400;
55
- color: var(--blue-dark);
56
- margin: 0 0 5px 0;
57
- }
58
- .data-block h5 pnx-button { vertical-align: middle; }
59
- .data-block h5 svg.svg-inline--fa { height: 14px; }
60
- .data-block div {
61
- font-size: 0.8em;
62
44
  }
63
45
 
64
46
  pnx-semantics-table {
@@ -70,14 +52,8 @@ export default class PictureMetadata extends LitElement {
70
52
  /** @private */
71
53
  static properties = {
72
54
  _meta: {state: true},
73
- _semanticsPicShowAll: {state: true},
74
55
  };
75
56
 
76
- constructor() {
77
- super();
78
- this._semanticsPicShowAll = false;
79
- }
80
-
81
57
  /** @private */
82
58
  connectedCallback() {
83
59
  super.connectedCallback();
@@ -238,61 +214,6 @@ export default class PictureMetadata extends LitElement {
238
214
  ];
239
215
  }
240
216
 
241
- // Semantics data
242
- const hasSemantics = (
243
- (this._meta.properties.semantics || []).length > 0
244
- || (this._meta.properties.annotations || []).length > 0
245
- );
246
- let semanticsData = [];
247
- if(hasSemantics) {
248
- // Hashtags
249
- const hashtags = getHashTags(this._meta);
250
- if(hashtags.length > 0) {
251
- semanticsData.push({
252
- title: this._parent?._t.pnx.semantics_hashtags,
253
- style: "width: 100%",
254
- content: hashtags.join(" ")
255
- });
256
- }
257
-
258
- // Full list of picture tags
259
- semanticsData.push({
260
- title: this._parent?._t.pnx.semantics_tags_picture,
261
- style: "width: 100%",
262
- content: html`${this._meta.properties.semantics?.length > 0
263
- ? html`
264
- <pnx-button
265
- kind="outline"
266
- size="sm"
267
- style="width: 100%"
268
- @click=${() => this._semanticsPicShowAll = !this._semanticsPicShowAll}
269
- >
270
- ${this._semanticsPicShowAll ? fa(faChevronUp) : fa(faChevronDown)}
271
- ${this._semanticsPicShowAll ? this._parent?._t.pnx.semantics_hide_all_tags : this._parent?._t.pnx.semantics_show_all_tags}
272
- </pnx-button>
273
- <pnx-semantics-table
274
- ._t=${this._parent?._t}
275
- .source=${this._meta.properties}
276
- style="margin-top: 5px"
277
- class=${this._semanticsPicShowAll ? "":"pnx-hidden"}
278
- />
279
- `
280
- : this._parent?._t.pnx.semantics_tags_picture_none
281
- }`
282
- });
283
-
284
- // Annotations (features in picture)
285
- semanticsData.push({
286
- title: this._parent?._t.pnx.semantics_features,
287
- style: "width: 100%",
288
- content: html`
289
- ${this._meta.properties.annotations?.length > 0
290
- ? html`<pnx-annotations-list ._parent=${this._parent} />`
291
- : this._parent?._t.pnx.semantics_features_none}
292
- `
293
- });
294
- }
295
-
296
217
  // EXIF data
297
218
  const exifData = Object.entries(this._meta.properties.exif)
298
219
  .sort()
@@ -426,10 +347,11 @@ export default class PictureMetadata extends LitElement {
426
347
  qualityData
427
348
  ) : nothing}
428
349
 
429
- ${hasSemantics ? this._toTab( // Semantics
430
- html`${fa(faTags)} ${this._parent?._t.pnx.semantics_title}`,
431
- semanticsData
432
- ) : nothing}
350
+ <h4 slot="title">${fa(faTags)} ${this._parent?._t.pnx.semantics_title}</h4>
351
+ <div slot="content" class="data-blocks">
352
+ <pnx-semantics-metadata ._parent=${this._parent}></pnx-semantics-metadata>
353
+ </div>
354
+ </div>
433
355
 
434
356
  ${this._meta.properties?.exif ? this._toTab( // EXIF
435
357
  html`${fa(faScroll)} ${this._parent?._t.pnx.metadata_exif}`,
@@ -0,0 +1,186 @@
1
+ import { LitElement, html, nothing, css } from "lit";
2
+ import { fa, onceParentAvailable } from "../../utils/widgets";
3
+ import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown";
4
+ import { faChevronUp } from "@fortawesome/free-solid-svg-icons/faChevronUp";
5
+ import { faPen } from "@fortawesome/free-solid-svg-icons/faPen";
6
+ import { faFloppyDisk } from "@fortawesome/free-solid-svg-icons/faFloppyDisk";
7
+ import { faRotateLeft } from "@fortawesome/free-solid-svg-icons/faRotateLeft";
8
+ import { getHashTags } from "../../utils/picture";
9
+ import { hidden, dataBlocks } from "../styles";
10
+ import { getUserAccount } from "../../utils/utils";
11
+
12
+ /**
13
+ * Semantics metadata displays detailed info about semantic attributes of a single picture.
14
+ * @class Panoramax.components.menus.SemanticsMetadata
15
+ * @element pnx-semantics-metadata
16
+ * @extends [lit.LitElement](https://lit.dev/docs/api/LitElement/)
17
+ * @example
18
+ * ```html
19
+ * <pnx-semantics-metadata ._parent=${viewer}></pnx-semantics-metadata>
20
+ * ```
21
+ */
22
+ export default class SemanticsMetadata extends LitElement {
23
+ /** @private */
24
+ static styles = [ hidden, dataBlocks, css`
25
+ .data-block {
26
+ width: 100%;
27
+ }
28
+ ` ];
29
+
30
+ /** @private */
31
+ static properties = {
32
+ _meta: {state: true},
33
+ _picShowAll: {state: true},
34
+ _editPicSem: {state: true},
35
+ _editedPicSemTags: {state: true},
36
+ };
37
+
38
+ constructor() {
39
+ super();
40
+ this._meta = {};
41
+ this._picShowAll = false;
42
+ this._editPicSem = false;
43
+ this._editedPicSemTags = null;
44
+ }
45
+
46
+ /** @private */
47
+ connectedCallback() {
48
+ super.connectedCallback();
49
+
50
+ onceParentAvailable(this).then(() => {
51
+ this._meta = this._parent?.psv?.getPictureMetadata();
52
+ this._parent?.oncePSVReady?.().then(() => {
53
+ this._parent.psv.addEventListener("picture-loaded", () => {
54
+ this._meta = this._parent.psv.getPictureMetadata();
55
+ });
56
+ this._parent.psv.addEventListener("annotation-click", () => {
57
+ const tabs = this.shadowRoot.querySelector("pnx-tabs");
58
+ if(tabs) { tabs.setAttribute("activeTabIndex", 4); }
59
+ });
60
+ });
61
+ });
62
+ }
63
+
64
+ /** @private */
65
+ _onStartEditPicSem() {
66
+ this._editedPicSemTags = null;
67
+ this._editPicSem = true;
68
+ }
69
+
70
+ /** @private */
71
+ _onPicSemEditorChange(e) {
72
+ this._editedPicSemTags = e.detail;
73
+ }
74
+
75
+ /** @private */
76
+ _onSavePicSem() {
77
+ const field = this.renderRoot.querySelector("#pnx-sem-pic-editor");
78
+
79
+ // Check field validity
80
+ if(!field || !field.checkValidity()) {
81
+ alert(this._parent?._t.pnx.semantics_cantsave_invalid);
82
+ return;
83
+ }
84
+
85
+ // Send changes to API
86
+ this._parent?.api.sendPictureSemantics(this._meta, this._editedPicSemTags.delta).then(newPic => {
87
+ const newMeta = Object.assign({}, this._meta);
88
+ newMeta.properties.semantics = newPic.properties.semantics;
89
+ this._meta = newMeta;
90
+ this._editPicSem = false;
91
+ alert(this._parent?._t.pnx.semantics_send_ok);
92
+ }).catch(e => {
93
+ this._editPicSem = false;
94
+ alert(this._parent?._t.pnx.semantics_send_fail);
95
+ console.error("Can't send semantics", e);
96
+ });
97
+ }
98
+
99
+ /** @private */
100
+ render() {
101
+ /* eslint-disable indent */
102
+ if(!this._meta?.properties) { return; }
103
+
104
+ const hashtags = getHashTags(this._meta);
105
+ const canEdit = !this._meta.origInstance && getUserAccount() !== null;
106
+
107
+ return html`
108
+ ${hashtags.length > 0 ? html`
109
+ <div class="data-block">
110
+ <h5>${this._parent?._t.pnx.semantics_hashtags}</h5>
111
+ <div>${hashtags.join(" ")}</div>
112
+ </div>
113
+ ` : nothing}
114
+
115
+ <div class="data-block">
116
+ <h5>
117
+ ${this._parent?._t.pnx.semantics_tags_picture}
118
+
119
+ ${canEdit && this._editPicSem ?
120
+ html`<pnx-button-group style="display: inline-block; vertical-align: middle;">
121
+ <pnx-button
122
+ kind="superinline"
123
+ title=${this._parent?._t.pnx.semantics_undo}
124
+ @click=${() => this._editPicSem = false}
125
+ >
126
+ ${fa(faRotateLeft)}
127
+ </pnx-button>
128
+ <pnx-button
129
+ kind="superinline"
130
+ title=${this._parent?._t.pnx.semantics_save}
131
+ @click=${this._onSavePicSem}
132
+ >
133
+ ${fa(faFloppyDisk)}
134
+ </pnx-button>
135
+ </pnx-button-group>`
136
+ : (canEdit ? html`<pnx-button
137
+ kind="superinline"
138
+ title=${this._parent?._t.pnx.semantics_edit}
139
+ @click=${this._onStartEditPicSem}
140
+ >
141
+ ${fa(faPen)}
142
+ </pnx-button>` : "")
143
+ }
144
+ </h5>
145
+ <div>
146
+ ${this._editPicSem ? html`
147
+ <pnx-semantics-editor
148
+ id="pnx-sem-pic-editor"
149
+ .semantics=${this._editedPicSemTags ? this._editedPicSemTags.semantics : this._meta.properties.semantics}
150
+ ._t=${this._parent._t}
151
+ @change=${this._onPicSemEditorChange}
152
+ ></pnx-semantics-editor>
153
+ ` : html`
154
+ ${this._meta.properties.semantics?.length > 0 ? html`
155
+ <pnx-button
156
+ kind="outline"
157
+ size="sm"
158
+ style="width: 100%"
159
+ @click=${() => this._picShowAll = !this._picShowAll}
160
+ >
161
+ ${this._picShowAll ? fa(faChevronUp) : fa(faChevronDown)}
162
+ ${this._picShowAll ? this._parent?._t.pnx.semantics_hide_all_tags : this._parent?._t.pnx.semantics_show_all_tags}
163
+ </pnx-button>
164
+ <pnx-semantics-table
165
+ ._t=${this._parent?._t}
166
+ .source=${this._meta.properties}
167
+ style="margin-top: 5px"
168
+ class=${this._picShowAll ? "":"pnx-hidden"}
169
+ />`
170
+ : this._parent?._t.pnx.semantics_tags_picture_none}
171
+ `}
172
+ </div>
173
+ </div>
174
+
175
+ <div class="data-block">
176
+ <h5>${this._parent?._t.pnx.semantics_features}</h5>
177
+ <div>${this._meta.properties.annotations?.length > 0
178
+ ? html`<pnx-annotations-list ._parent=${this._parent} />`
179
+ : this._parent?._t.pnx.semantics_features_none}
180
+ </div>
181
+ </div>
182
+ `;
183
+ }
184
+ }
185
+
186
+ customElements.define("pnx-semantics-metadata", SemanticsMetadata);
@@ -14,4 +14,5 @@ export {default as PictureMetadata} from "./PictureMetadata";
14
14
  export {default as PlayerOptions} from "./PlayerOptions";
15
15
  export {default as QualityScoreDoc} from "./QualityScoreDoc";
16
16
  export {default as ReportForm} from "./ReportForm";
17
+ export {default as SemanticsMetadata} from "./SemanticsMetadata";
17
18
  export {default as Share} from "./Share";
@@ -149,6 +149,7 @@ export const btn = css`
149
149
  .pnx-btn ::slotted(.svg-inline--fa),
150
150
  .pnx-btn slot .svg-inline--fa {
151
151
  height: 16px;
152
+ pointer-events: none;
152
153
  }
153
154
 
154
155
  /* Sizing */
@@ -487,3 +488,24 @@ export const iconify = css`
487
488
  height: 1em;
488
489
  }
489
490
  `;
491
+
492
+ // Tabbed-legend data blocks
493
+ export const dataBlocks = css`
494
+ .data-block {
495
+ display: inline-block;
496
+ margin: 8px 0;
497
+ box-sizing: border-box;
498
+ vertical-align: top;
499
+ }
500
+ .data-block h5 {
501
+ font-size: 0.8em;
502
+ font-weight: 400;
503
+ color: var(--blue-dark);
504
+ margin: 0 0 5px 0;
505
+ }
506
+ .data-block h5 pnx-button { vertical-align: middle; }
507
+ .data-block h5 svg.svg-inline--fa { height: 14px; }
508
+ .data-block div {
509
+ font-size: 0.8em;
510
+ }
511
+ `;
@@ -82,7 +82,7 @@ export default class SemanticsEditor extends LitElement {
82
82
  getDiff() {
83
83
  return computeDiffTags(this._firstSemantics || [], this.semantics);
84
84
  }
85
-
85
+
86
86
  /**
87
87
  * Check if input is having a valid value.
88
88
  * @memberof Panoramax.components.ui.SemanticsEditor#
@@ -91,6 +91,18 @@ export default class SemanticsEditor extends LitElement {
91
91
  checkValidity() {
92
92
  return this._valid;
93
93
  }
94
+
95
+ /**
96
+ * Forces Editor to goes back to its empty, initial state.
97
+ * @param {object} [baseSemantics=null] Initial existing semantics you want to show in editor. This is useful for getting a diff of only new semantic entries. Leave empty if no tags pre-exist.
98
+ * @memberof Panoramax.components.ui.SemanticsEditor#
99
+ */
100
+ reset(baseSemantics = null) {
101
+ this.semantics = null;
102
+ this._valid = true;
103
+ this._firstSemantics = baseSemantics;
104
+ this.semantics = baseSemantics;
105
+ }
94
106
 
95
107
  /** @private */
96
108
  _onInput(e) {
@@ -144,7 +156,7 @@ export default class SemanticsEditor extends LitElement {
144
156
  autocorrect="off"
145
157
  autocapitalize="off"
146
158
  spellcheck="false"
147
- placeholder="key1=value1\nprefix|key2=value2"
159
+ placeholder=${this._t?.pnx.semantics_editor_example || "key1=value1\nprefix|key2=value2"}
148
160
  @input=${this._onInput}
149
161
  @blur=${this._onBlur}
150
162
  rows=${this.rows}
@@ -16,6 +16,7 @@ import { groupByPrefix } from "../../utils/semantics";
16
16
  export default class SemanticsTable extends LitElement {
17
17
  /** @private */
18
18
  static styles = [ table, css`
19
+ :host { display: block; }
19
20
  th:first-child, td:first-child { width: 30%; }
20
21
  td { vertical-align: top; }
21
22
 
@@ -200,6 +200,13 @@
200
200
  "P361": "part of"
201
201
  },
202
202
  "semantics_editor_error": "The syntax is invalid. Your tags may look like:\nkey=value\nprefix|key=value\nprefix|key[qualif_key=qualif_val]=value\n\nMax key length is 256 characters, max value length 2048 characters.",
203
+ "semantics_editor_example": "key=value\nprefix|key=value",
204
+ "semantics_edit": "Edit attributes",
205
+ "semantics_save": "Save your edits",
206
+ "semantics_undo": "Cancel your edits",
207
+ "semantics_cantsave_invalid": "Can't save your attributes, input is not valid",
208
+ "semantics_send_fail": "We can't send your edits for now, please retry later.",
209
+ "semantics_send_ok": "Your edits were successfully sent",
203
210
  "report": "Report",
204
211
  "report_auth": "This report will be sent using your account \"{a}\"",
205
212
  "report_nature_label": "Nature of the issue",