@loadbare/widgets 0.10.0 → 0.10.1

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/README.md CHANGED
@@ -19,6 +19,8 @@ Inventory:
19
19
  | [`lb-checkbox`](docs/lb-checkbox.md) | a checkbox and its label, as markup to style |
20
20
  | [`lb-number`](docs/lb-number.md) | a number shown by `Intl.NumberFormat` |
21
21
  | [`lb-date`](docs/lb-date.md) | a date or time shown by `Intl.DateTimeFormat` |
22
+ | [`lb-tel`](docs/lb-tel.md) | a phone number shown as a `tel:` link |
23
+ | [`lb-mailto`](docs/lb-mailto.md) | an email address shown as a `mailto:` link |
22
24
 
23
25
  ## Installing
24
26
 
package/dist/index.d.ts CHANGED
@@ -7,4 +7,6 @@ import "./lb-confirm.browser.js";
7
7
  import "./lb-insert-dialog.browser.js";
8
8
  import "./lb-number.browser.js";
9
9
  import "./lb-date.browser.js";
10
+ import "./lb-tel.browser.js";
11
+ import "./lb-mailto.browser.js";
10
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../widgets/index.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,yBAAyB,CAAC;AACjC,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,yBAAyB,CAAC;AACjC,OAAO,+BAA+B,CAAC;AACvC,OAAO,wBAAwB,CAAC;AAChC,OAAO,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../widgets/index.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,yBAAyB,CAAC;AACjC,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,yBAAyB,CAAC;AACjC,OAAO,+BAA+B,CAAC;AACvC,OAAO,wBAAwB,CAAC;AAChC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,wBAAwB,CAAC"}
package/dist/index.js CHANGED
@@ -7,4 +7,6 @@ import "./lb-confirm.browser.js";
7
7
  import "./lb-insert-dialog.browser.js";
8
8
  import "./lb-number.browser.js";
9
9
  import "./lb-date.browser.js";
10
+ import "./lb-tel.browser.js";
11
+ import "./lb-mailto.browser.js";
10
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../widgets/index.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,yBAAyB,CAAC;AACjC,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,yBAAyB,CAAC;AACjC,OAAO,+BAA+B,CAAC;AACvC,OAAO,wBAAwB,CAAC;AAChC,OAAO,sBAAsB,CAAC","sourcesContent":["import \"./lb-input.browser.js\";\nimport \"./lb-select.browser.js\";\nimport \"./lb-options.browser.js\";\nimport \"./lb-table.browser.js\";\nimport \"./lb-picker.browser.js\";\nimport \"./lb-confirm.browser.js\";\nimport \"./lb-insert-dialog.browser.js\";\nimport \"./lb-number.browser.js\";\nimport \"./lb-date.browser.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../widgets/index.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,yBAAyB,CAAC;AACjC,OAAO,uBAAuB,CAAC;AAC/B,OAAO,wBAAwB,CAAC;AAChC,OAAO,yBAAyB,CAAC;AACjC,OAAO,+BAA+B,CAAC;AACvC,OAAO,wBAAwB,CAAC;AAChC,OAAO,sBAAsB,CAAC;AAC9B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,wBAAwB,CAAC","sourcesContent":["import \"./lb-input.browser.js\";\nimport \"./lb-select.browser.js\";\nimport \"./lb-options.browser.js\";\nimport \"./lb-table.browser.js\";\nimport \"./lb-picker.browser.js\";\nimport \"./lb-confirm.browser.js\";\nimport \"./lb-insert-dialog.browser.js\";\nimport \"./lb-number.browser.js\";\nimport \"./lb-date.browser.js\";\nimport \"./lb-tel.browser.js\";\nimport \"./lb-mailto.browser.js\";\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=lb-mailto.browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lb-mailto.browser.d.ts","sourceRoot":"","sources":["../widgets/lb-mailto.browser.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ /// <reference lib="dom" />
2
+ import { ATTR_COLUMN_VALUE } from "@loadbare/app/constants";
3
+ /**
4
+ * Shows the value that landed on it as written, in the `<a>` its definition
5
+ * holds, with a `mailto:` `href` that writes to it. Not a control: the hub
6
+ * stamps `lb-column-value` on the tag and never gathers it.
7
+ *
8
+ * The address is encoded into the `href`, so a value carrying `?` or `&`
9
+ * cannot add a subject, a body or another recipient to the message. A value
10
+ * with no `@` shows as it arrived, with no `href`.
11
+ */
12
+ class LbMailto extends HTMLElement {
13
+ static observedAttributes = [ATTR_COLUMN_VALUE];
14
+ attributeChangedCallback(_name, _old, value) {
15
+ const a = this.querySelector("a");
16
+ if (!a)
17
+ return;
18
+ a.textContent = value ?? "";
19
+ const address = value?.trim();
20
+ if (address?.includes("@")) {
21
+ a.setAttribute("href", `mailto:${encodeURIComponent(address).replace(/%40/g, "@")}`);
22
+ }
23
+ else {
24
+ a.removeAttribute("href");
25
+ }
26
+ }
27
+ }
28
+ customElements.define("lb-mailto", LbMailto);
29
+ //# sourceMappingURL=lb-mailto.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lb-mailto.browser.js","sourceRoot":"","sources":["../widgets/lb-mailto.browser.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D;;;;;;;;GAQG;AACH,MAAM,QAAS,SAAQ,WAAW;IAChC,MAAM,CAAC,kBAAkB,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEhD,wBAAwB,CACtB,KAAa,EACb,IAAmB,EACnB,KAAoB;QAEpB,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,CAAC,CAAC,WAAW,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,KAAK,EAAE,IAAI,EAAE,CAAC;QAC9B,IAAI,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC3B,CAAC,CAAC,YAAY,CACZ,MAAM,EACN,UAAU,kBAAkB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAC7D,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;;AAGH,cAAc,CAAC,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC","sourcesContent":["/// <reference lib=\"dom\" />\n\nimport { ATTR_COLUMN_VALUE } from \"@loadbare/app/constants\";\n\n/**\n * Shows the value that landed on it as written, in the `<a>` its definition\n * holds, with a `mailto:` `href` that writes to it. Not a control: the hub\n * stamps `lb-column-value` on the tag and never gathers it.\n *\n * The address is encoded into the `href`, so a value carrying `?` or `&`\n * cannot add a subject, a body or another recipient to the message. A value\n * with no `@` shows as it arrived, with no `href`.\n */\nclass LbMailto extends HTMLElement {\n static observedAttributes = [ATTR_COLUMN_VALUE];\n\n attributeChangedCallback(\n _name: string,\n _old: string | null,\n value: string | null,\n ): void {\n const a = this.querySelector(\"a\");\n if (!a) return;\n a.textContent = value ?? \"\";\n const address = value?.trim();\n if (address?.includes(\"@\")) {\n a.setAttribute(\n \"href\",\n `mailto:${encodeURIComponent(address).replace(/%40/g, \"@\")}`,\n );\n } else {\n a.removeAttribute(\"href\");\n }\n }\n}\n\ncustomElements.define(\"lb-mailto\", LbMailto);\n"]}
@@ -0,0 +1,6 @@
1
+ <!--
2
+ An email address as a mailto: link. The script writes the href from the
3
+ value, so the definition is an <a> with none: until a value lands it is
4
+ not a link.
5
+ -->
6
+ <a></a>
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=lb-tel.browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lb-tel.browser.d.ts","sourceRoot":"","sources":["../widgets/lb-tel.browser.ts"],"names":[],"mappings":""}
@@ -0,0 +1,40 @@
1
+ /// <reference lib="dom" />
2
+ import { ATTR_COLUMN_VALUE } from "@loadbare/app/constants";
3
+ /**
4
+ * Shows the value that landed on it as written, in the `<a>` its definition
5
+ * holds, with a `tel:` `href` that dials it. Not a control: the hub stamps
6
+ * `lb-column-value` on the tag and never gathers it.
7
+ *
8
+ * The `href` keeps a leading `+` and the digits, and drops the rest, so
9
+ * `(555) 123-4567` dials as `5551234567`. An extension written after `x`,
10
+ * `ext` or `extension` becomes `;ext=`, rather than digits dialed on the end
11
+ * of the number. A value with no digits shows as it arrived, with no `href`.
12
+ */
13
+ class LbTel extends HTMLElement {
14
+ static observedAttributes = [ATTR_COLUMN_VALUE];
15
+ attributeChangedCallback(_name, _old, value) {
16
+ const a = this.querySelector("a");
17
+ if (!a)
18
+ return;
19
+ a.textContent = value ?? "";
20
+ const href = value === null ? null : tel(value);
21
+ if (href)
22
+ a.setAttribute("href", href);
23
+ else
24
+ a.removeAttribute("href");
25
+ }
26
+ }
27
+ /** The `tel:` URI for a number as a person writes it, null for no number. */
28
+ function tel(value) {
29
+ const [number, ext] = value.split(EXTENSION, 2);
30
+ const digits = number.replace(/\D/g, "");
31
+ if (!digits)
32
+ return null;
33
+ const plus = number.trim().startsWith("+") ? "+" : "";
34
+ const extDigits = ext?.replace(/\D/g, "");
35
+ return `tel:${plus}${digits}${extDigits ? `;ext=${extDigits}` : ""}`;
36
+ }
37
+ /** Where a number ends and its extension begins. */
38
+ const EXTENSION = /\s*(?:extension|ext\.?|x)\s*(?=\d)/i;
39
+ customElements.define("lb-tel", LbTel);
40
+ //# sourceMappingURL=lb-tel.browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lb-tel.browser.js","sourceRoot":"","sources":["../widgets/lb-tel.browser.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D;;;;;;;;;GASG;AACH,MAAM,KAAM,SAAQ,WAAW;IAC7B,MAAM,CAAC,kBAAkB,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAEhD,wBAAwB,CACtB,KAAa,EACb,IAAmB,EACnB,KAAoB;QAEpB,MAAM,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,CAAC,CAAC,WAAW,GAAG,KAAK,IAAI,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,IAAI;YAAE,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;;YAClC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IACjC,CAAC;;AAGH,6EAA6E;AAC7E,SAAS,GAAG,CAAC,KAAa;IACxB,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACtD,MAAM,SAAS,GAAG,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAC1C,OAAO,OAAO,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,QAAQ,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AACvE,CAAC;AAED,oDAAoD;AACpD,MAAM,SAAS,GAAG,qCAAqC,CAAC;AAExD,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC","sourcesContent":["/// <reference lib=\"dom\" />\n\nimport { ATTR_COLUMN_VALUE } from \"@loadbare/app/constants\";\n\n/**\n * Shows the value that landed on it as written, in the `<a>` its definition\n * holds, with a `tel:` `href` that dials it. Not a control: the hub stamps\n * `lb-column-value` on the tag and never gathers it.\n *\n * The `href` keeps a leading `+` and the digits, and drops the rest, so\n * `(555) 123-4567` dials as `5551234567`. An extension written after `x`,\n * `ext` or `extension` becomes `;ext=`, rather than digits dialed on the end\n * of the number. A value with no digits shows as it arrived, with no `href`.\n */\nclass LbTel extends HTMLElement {\n static observedAttributes = [ATTR_COLUMN_VALUE];\n\n attributeChangedCallback(\n _name: string,\n _old: string | null,\n value: string | null,\n ): void {\n const a = this.querySelector(\"a\");\n if (!a) return;\n a.textContent = value ?? \"\";\n const href = value === null ? null : tel(value);\n if (href) a.setAttribute(\"href\", href);\n else a.removeAttribute(\"href\");\n }\n}\n\n/** The `tel:` URI for a number as a person writes it, null for no number. */\nfunction tel(value: string): string | null {\n const [number, ext] = value.split(EXTENSION, 2);\n const digits = number.replace(/\\D/g, \"\");\n if (!digits) return null;\n const plus = number.trim().startsWith(\"+\") ? \"+\" : \"\";\n const extDigits = ext?.replace(/\\D/g, \"\");\n return `tel:${plus}${digits}${extDigits ? `;ext=${extDigits}` : \"\"}`;\n}\n\n/** Where a number ends and its extension begins. */\nconst EXTENSION = /\\s*(?:extension|ext\\.?|x)\\s*(?=\\d)/i;\n\ncustomElements.define(\"lb-tel\", LbTel);\n"]}
@@ -0,0 +1,6 @@
1
+ <!--
2
+ A phone number as a tel: link. The script writes the href from the value,
3
+ so the definition is an <a> with none: until a value lands it is not a
4
+ link.
5
+ -->
6
+ <a></a>
@@ -0,0 +1,29 @@
1
+ # `lb-mailto`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ An email address shown as written, as a `mailto:` link. Not a control:
6
+ write `lb-column` on the tag, and the hub lands the column on it and never
7
+ gathers it.
8
+
9
+ ```html
10
+ <lb-mailto lb-column="email"></lb-mailto>
11
+ ```
12
+
13
+ It takes no parameters. To edit the address, use
14
+ `<lb-input exp-type="email">`.
15
+
16
+ ## The value
17
+
18
+ The link's text is the value as it arrived. Its `href` is `mailto:` and the
19
+ address, encoded, so a value carrying `?` or `&` cannot add a subject, a body
20
+ or another recipient to the message.
21
+
22
+ A value with no `@` shows as it arrived, with no `href`. Null shows
23
+ nothing.
24
+
25
+ ## Styling
26
+
27
+ The definition is an `<a>`, with no `href` while there is no address, so
28
+ `lb-mailto a:not([href])` selects a value that is no link. The hub stamps
29
+ the tag with `lb-column-value`, the value as it arrived.
package/docs/lb-tel.md ADDED
@@ -0,0 +1,32 @@
1
+ # `lb-tel`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A phone number shown as written, as a `tel:` link. Not a control: write
6
+ `lb-column` on the tag, and the hub lands the column on it and never gathers
7
+ it.
8
+
9
+ ```html
10
+ <lb-tel lb-column="phone"></lb-tel>
11
+ ```
12
+
13
+ It takes no parameters. To edit the number, use
14
+ `<lb-input exp-type="tel">`.
15
+
16
+ ## The value
17
+
18
+ The link's text is the value as it arrived. Its `href` keeps a leading `+`
19
+ and the digits, and drops everything else, so `(555) 123-4567` dials
20
+ `tel:5551234567`.
21
+
22
+ An extension written after `x`, `ext`, `ext.` or `extension` goes in the
23
+ `href` as `;ext=`, so `555-123-4567 x89` dials `tel:5551234567;ext=89`.
24
+
25
+ A value with no digits shows as it arrived, with no `href`. Null shows
26
+ nothing.
27
+
28
+ ## Styling
29
+
30
+ The definition is an `<a>`, with no `href` while there is nothing to dial,
31
+ so `lb-tel a:not([href])` selects a number that is no link. The hub stamps
32
+ the tag with `lb-column-value`, the value as it arrived.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@loadbare/widgets",
3
- "description": "The basic widget set for @loadbare/app: input, select, options, picker, table, unknown-page, confirm, form, insert-dialog, master, checkbox, number, date",
4
- "version": "0.10.0",
3
+ "description": "The basic widget set for @loadbare/app: input, select, options, picker, table, unknown-page, confirm, form, insert-dialog, master, checkbox, number, date, tel, mailto",
4
+ "version": "0.10.1",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -1,130 +0,0 @@
1
- # Feature request: `lb-table` for maintenance pages
2
-
3
- Temporary. Written from the rkmedia app, which uses `lb-table` for every
4
- list it edits (lookup tables with a ghost row, edit-in-place cells,
5
- drag-to-reorder). Two things every such page wants and today writes for
6
- itself, or cannot have. To be settled here and then folded into
7
- `lb-table.md` or deleted.
8
-
9
- ## 1. The order shown on the heading, and re-sorted from it
10
-
11
- **Status:** first iteration implemented, as settled below; see
12
- `lb-table.md`, *The order on the heading*.
13
-
14
- **Want:** `lb-table` always marks the heading of the column the rows are
15
- sorted by with an up or down triangle for the direction. While the order is
16
- dirty from the user's edits (`lb-query-unsorted-count` is not 0), the
17
- triangle changes color. Clicking the heading sorts by its column.
18
-
19
- **Why:** an edit from a control in a row, or from the ghost row, leaves the
20
- rows where they stand (`lb-table.md`, *Order and groups*). Every table
21
- whose order reads a column the user edits needs a re-sort control, so every
22
- page writes the same markup and CSS. What rkmedia writes today:
23
-
24
- ```html
25
- <div class="list">
26
- <button type="button" class="resort" commandfor="workshop-topics-list" command="--lb-sort">Re-sort</button>
27
- <lb-table id="workshop-topics-list" lb-query="workshopTopics" exp-caption="Talks and workshops">
28
- ...
29
- </lb-table>
30
- </div>
31
- ```
32
-
33
- ```css
34
- .resort { visibility: hidden; }
35
- :has(> [lb-query-unsorted-count]:not([lb-query-unsorted-count="0"])) > .resort { visibility: visible; }
36
- ```
37
-
38
- The button cannot go inside the tag, so it needs an `id`, `commandfor` and
39
- a `:has()` on a wrapper. Shown with `display` it moves the table; shown
40
- with `visibility` it leaves a blank strip above every table.
41
-
42
- The heading row is always laid out and the widget owns it, so the
43
- triangle placed there moves nothing, needs no `id` and no page CSS. The
44
- hub already knows the order: the server declares it, and `lb-order` names
45
- the user's.
46
-
47
- **Settled:**
48
-
49
- - **The triangle is always shown** on the sorted column's heading, clean or
50
- dirty.
51
- - **Dirty is a color change** on the triangle.
52
- - **Clicking a dirty triangle re-sorts** (`--lb-sort`): it places the rows
53
- and clears `lb-row-unsorted`, keeping the direction. Only a click on a
54
- clean triangle reverses.
55
- - **Clicking another heading sorts by its column**, writing the user's
56
- order (`lb-order`). That places every row and clears `lb-row-unsorted`.
57
- - **Raw values.** A column shown formatted sorts by what the query sent,
58
- so it must be sent raw or declared in `types` (the reference already says
59
- so); worth repeating in `lb-table.md`.
60
- - **A default style for `tr[lb-row-unsorted]`** (rkmedia marks the first
61
- cell's left edge), subtle and overridable, saves every app writing one.
62
- - **A heading takes its column from the row template.** The nth heading
63
- shows the column of the nth cell of the row template, the `lb-column` in
64
- that cell. The page writes nothing on the `<th>`. A cell with no
65
- `lb-column`, or with several, gives its heading no column, and that
66
- heading does not sort.
67
- - **One column at a time.** A heading click writes an order of one term.
68
- When the order has several terms, the triangle marks the leading term.
69
- Sub-sorts are a UI question for later, built on this foundation.
70
- - **Groups leave all of this out.** A table with group templates shows no
71
- triangle and takes no heading clicks, so none of it triggers there.
72
- - **Dirty is yellow, circled.** The triangle turns yellow and gains a
73
- circle around it, so the shape says dirty without the color.
74
- - **No route back to the server's order.** Once the user sorts by a
75
- heading, the user's order stands.
76
- - **No sort is the opt-out.** A table with no order shows no triangle and
77
- takes no heading clicks.
78
-
79
- **Open:**
80
-
81
- - **The order's column not shown.** A drag-to-reorder table orders by a
82
- position column no one displays, and a server's order may lead with any
83
- column the template leaves out. No heading carries the triangle, so a
84
- dirty order has no re-sort control. Either the triangle has an
85
- always-present fallback, such tables keep a page-written button, or the
86
- dirty state cannot arise for them (a drag rewrites positions so no row
87
- stands out of order).
88
- - **Heading clicks without `lb-order`.** A heading click writes the user's
89
- order into the column of `lb-choices` that `lb-order` names. A table
90
- with a server order and no `lb-order` has nowhere to write it: it can
91
- show the triangle and re-sort from it, but not sort by another heading.
92
- Whether that is the intended reading of "no sort", or the widget
93
- supplies a choice of its own.
94
-
95
- The first iteration takes the plain reading of both: a table whose order's
96
- leading column has no heading shows no triangle and keeps a page-written
97
- button, and a table without `lb-order` shows the triangle and re-sorts
98
- from it but takes no clicks on other headings.
99
-
100
- ## 2. Highlight-to-filter that works on edit pages
101
-
102
- **Want:** select text in a cell and the table filters to the rows that
103
- match, on read-only and editable tables alike, and the table shows what it
104
- is filtered by.
105
-
106
- **What exists:** `lb-table.md`, *Filtering by selection*: a selection in a
107
- cell whose `lb-column` the table's `lb-filter` names becomes that column's
108
- choice (`=`, `^=`, `$=`, `*=`).
109
-
110
- **Gaps:**
111
-
112
- - **Inputs.** The widget reads `getSelection()`, which does not report text
113
- selected inside an `<input>` or `<textarea>`. An editable cell is an
114
- input, so on an edit page highlighting never filters. A control reports
115
- its own range (`selectionStart` / `selectionEnd`); the widget could read
116
- that when the selection is in one.
117
- - **Selecting is also editing.** In an input, selecting text is how you
118
- replace it, so filtering on every selection there would fight editing.
119
- It needs a gesture that means "filter": a modifier key held on mouse-up,
120
- or inputs that are `readonly`. Which gesture is Loadbare's call.
121
- - **No indicator.** Nothing on the table says it is filtered, by what, or
122
- offers to clear it; a page must add a control bound to `lb-choices`
123
- itself. With the re-sort on the heading, the caption line is free for
124
- this: the active filters with a clear button for each, and rows hidden
125
- ("12 of 40 shown"). Open whether the caption line is the place.
126
-
127
- ## Order of value to rkmedia
128
-
129
- 1, then 2. rkmedia has editable ordered tables now, will want heading
130
- sorts on the first long list, and has no filters yet.