app
Component Widgets
Public Made by Adomby adom
Reusable component widgets for pinouts, thermal vias, molecule relationships, reviewed chip outlines and lightweight four-level LOD cache listings.
← Commit history
adom-table: colorby="col:field" - colour a column from the data
Converting adom/repo-ownership's hand-built frame to this widget quietly dropped its
per-owner colour coding: every person had a coloured dot and name, and the widget rendered
them all in the same grey. Ray noticed the table had gone black and white. I had listed the
loss in my own notes and then never put it in front of him, which is the actual mistake.
The colour comes from the ROW, not from a palette in here: colorby="owner:owner_color"
paints the owner column using each row's owner_color. A widget cannot know a team's colours,
and hardcoding them would drift from the other renderings - repo-ownership paints its svg
export from the same map, so page and picture now cannot disagree.
Only #rgb / #rrggbb is accepted; anything else is dropped rather than written into a style
attribute, so a data file can never inject CSS through this.
1 file changed
+21−1
widgets/adom-table.js+21−1@@ -511,6 +511,12 @@ * facet="owner" add a dropdown that filters on one column's distinct values * sort="col" initial sort column; prefix "-" for descending * dim="key:value" render rows matching key=value at reduced opacity (e.g. archived)+ * colorby="col:field" colour the text (and a leading dot) of `col` using the CSS colour+ * carried in each row's `field`. The colour comes from the DATA, not from+ * a palette in here, so a page and its other renderings (an svg export,+ * say) cannot drift into disagreeing about who is which colour. Only+ * #rgb / #rrggbb is accepted; anything else is dropped rather than+ * written into a style attribute. * mark="style:key:re[; ...]" colour cells whose value matches a pattern, e.g. * mark="warn:rule:PR ONLY|ASK; accent:rule:^merge:" * styles: warn (red) accent (blue) ok (green). The cell text is still@@ -546,7 +552,7 @@ } window.AdomWidget.define('adom-table', {- attributes: ['columns', 'heading', 'filter', 'facet', 'sort', 'dim', 'mark'],+ attributes: ['columns', 'heading', 'filter', 'facet', 'sort', 'dim', 'mark', 'colorby'], loadingText: 'Loading table', emptyText: 'No data supplied to <adom-table>', css: [@@ -563,6 +569,8 @@ 'th[aria-sort="descending"]:after{content:" \\2193"}', 'td{padding:5px 8px;border-bottom:1px solid var(--line2,#161b22);vertical-align:top}', 'tr.dim td{opacity:.45}',+ 'td .cdot{display:inline-block;width:8px;height:8px;border-radius:50%;margin-right:7px;',+ 'vertical-align:baseline;flex:none}', 'td.mk-warn{color:var(--aw-red,#f85149);font-weight:600}', 'td.mk-accent{color:var(--aw-blue,#58a6ff);font-weight:600}', 'td.mk-ok{color:var(--aw-green,#3fb950);font-weight:600}',@@ -602,6 +610,13 @@ var dim = (el.getAttribute('dim') || '').split(':'); // A malformed rule is dropped, never thrown: one bad pattern in an attribute must not // blank the whole table, which is the failure mode a guardrail page can least afford.+ // colorby="col:field" - never interpolate a raw cell value into a style attribute;+ // only a literal hex colour is allowed through.+ var cb = (el.getAttribute('colorby') || '').split(':');+ var colorCol = cb.length === 2 ? cb[0] : null, colorField = cb.length === 2 ? cb[1] : null;+ function safeColor(v) {+ return /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(String(v || '')) ? String(v) : null;+ } var marks = (el.getAttribute('mark') || '').split(';').map(function (rule) { var m = rule.trim().match(/^(warn|accent|ok):([^:]+):([\s\S]+)$/); if (!m) return null;@@ -643,6 +658,11 @@ cls = ' class="mk-' + marks[i].style + '"'; break; } }+ var col = (colorCol && c.key === colorCol) ? safeColor(r[colorField]) : null;+ if (col) {+ return '<td' + cls + ' style="color:' + col + '">' ++ '<span class=cdot style="background:' + col + '"></span>' + esc(v) + '</td>';+ } return '<td' + cls + '>' + esc(v) + '</td>'; }).join('') + '</tr>'; }).join('');