@wildwinter/app-shell 0.31.0 → 0.33.0

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/index.d.cts CHANGED
@@ -19,7 +19,20 @@ declare function el<K extends keyof HTMLElementTagNameMap>(tag: K, classNameOrPr
19
19
  * Its rollover is the THEMED one (`data-tip`), so an app that has called
20
20
  * `initTooltips()` gets our bubble rather than the platform's. */
21
21
  declare function iconBtn(glyph: string, title: string, onClick: () => void, disabled?: boolean, danger?: boolean): HTMLButtonElement;
22
- /** A captioned field: `<label class="shell-labelled"><span class="shell-fieldcap">…</span>control</label>`. */
22
+ /**
23
+ * A captioned field: `<label class="shell-labelled"><span class="shell-fieldcap">…</span>control</label>`.
24
+ *
25
+ * The label is pointed at the field it captions, EXPLICITLY, and never at a button. A `<label>` with no
26
+ * `for` forwards a click to its first labelable descendant, and buttons are labelable - so a caption
27
+ * wrapped around a control containing buttons (`tagChips`, whose every chip carries a remove button)
28
+ * turns every click on the row's dead space into a press of the FIRST button in it. That shipped:
29
+ * patterkit/patter#44, where clicking a Game Data list value anywhere but its ✕ deleted the first value
30
+ * in the list. Reported as "clicking a value removes the wrong one", which is not a wrong-index bug at
31
+ * all - the click never reached the chip.
32
+ *
33
+ * When the control holds no labelable field (a chips editor with the add input removed, say), this is a
34
+ * plain `<div>`: no caption behaviour is better than a caption that presses something.
35
+ */
23
36
  declare function labelled(label: string, control: HTMLElement): HTMLElement;
24
37
  /** Swap item `i` with its neighbour `i + delta` IN PLACE (the up/down reorder list editors share);
25
38
  * a no-op when the target is out of range. Returns whether anything moved. */
package/dist/index.d.ts CHANGED
@@ -19,7 +19,20 @@ declare function el<K extends keyof HTMLElementTagNameMap>(tag: K, classNameOrPr
19
19
  * Its rollover is the THEMED one (`data-tip`), so an app that has called
20
20
  * `initTooltips()` gets our bubble rather than the platform's. */
21
21
  declare function iconBtn(glyph: string, title: string, onClick: () => void, disabled?: boolean, danger?: boolean): HTMLButtonElement;
22
- /** A captioned field: `<label class="shell-labelled"><span class="shell-fieldcap">…</span>control</label>`. */
22
+ /**
23
+ * A captioned field: `<label class="shell-labelled"><span class="shell-fieldcap">…</span>control</label>`.
24
+ *
25
+ * The label is pointed at the field it captions, EXPLICITLY, and never at a button. A `<label>` with no
26
+ * `for` forwards a click to its first labelable descendant, and buttons are labelable - so a caption
27
+ * wrapped around a control containing buttons (`tagChips`, whose every chip carries a remove button)
28
+ * turns every click on the row's dead space into a press of the FIRST button in it. That shipped:
29
+ * patterkit/patter#44, where clicking a Game Data list value anywhere but its ✕ deleted the first value
30
+ * in the list. Reported as "clicking a value removes the wrong one", which is not a wrong-index bug at
31
+ * all - the click never reached the chip.
32
+ *
33
+ * When the control holds no labelable field (a chips editor with the add input removed, say), this is a
34
+ * plain `<div>`: no caption behaviour is better than a caption that presses something.
35
+ */
23
36
  declare function labelled(label: string, control: HTMLElement): HTMLElement;
24
37
  /** Swap item `i` with its neighbour `i + delta` IN PLACE (the up/down reorder list editors share);
25
38
  * a no-op when the target is out of range. Returns whether anything moved. */
package/dist/index.js CHANGED
@@ -181,8 +181,13 @@ function iconBtn(glyph, title, onClick, disabled = false, danger = false) {
181
181
  return b;
182
182
  }
183
183
  function labelled(label2, control) {
184
- const w = el("label", "shell-labelled");
184
+ const target = control.matches("input, select, textarea") ? control : control.querySelector("input:not([type=button]):not([type=submit]), select, textarea");
185
+ const w = el(target ? "label" : "div", "shell-labelled");
185
186
  w.append(el("span", "shell-fieldcap", label2), control);
187
+ if (target) {
188
+ if (!target.id) target.id = `shell-f-${Math.random().toString(36).slice(2, 9)}`;
189
+ w.htmlFor = target.id;
190
+ }
186
191
  return w;
187
192
  }
188
193
  function moveItem(arr, i, delta) {
@@ -976,8 +981,11 @@ function bindPropertyRef(input, onCommit, opts) {
976
981
  const list = document.createElement("datalist");
977
982
  list.id = `shell-propref-${Math.random().toString(36).slice(2, 9)}`;
978
983
  input.setAttribute("list", list.id);
979
- input.after(list);
984
+ const attach = () => {
985
+ if (!list.isConnected && input.parentNode) input.after(list);
986
+ };
980
987
  const sync = () => {
988
+ attach();
981
989
  const known = opts.known();
982
990
  list.replaceChildren(...known.map((k) => {
983
991
  const o = document.createElement("option");