flexdesk 0.17.15 → 0.17.16

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/css/base.css +224 -4
  3. package/css/flexdesk.css +314 -12
  4. package/dist/charts.js +104 -34
  5. package/dist/charts.js.map +3 -3
  6. package/dist/{chunk-2PM6ZMNS.js → chunk-2Z2ENHR3.js} +2 -2
  7. package/dist/{chunk-AD7FIA3Z.js → chunk-7JI7HHSY.js} +2 -2
  8. package/dist/{chunk-TLIV6QSU.js → chunk-7OL6F2AM.js} +3 -3
  9. package/dist/{chunk-MADMGRX2.js → chunk-PGZ4EHSE.js} +156 -9
  10. package/dist/chunk-PGZ4EHSE.js.map +7 -0
  11. package/dist/{chunk-OEG6NPAN.js → chunk-XJNADRGR.js} +2 -2
  12. package/dist/flexdesk.css +314 -12
  13. package/dist/flow.js +3 -3
  14. package/dist/tiles.js +84 -9
  15. package/dist/tiles.js.map +2 -2
  16. package/dist/widgets.js +448 -5
  17. package/dist/widgets.js.map +4 -4
  18. package/dist/wm.js +102 -14
  19. package/dist/wm.js.map +2 -2
  20. package/docs/README.md +1 -1
  21. package/docs/components/charts.md +70 -3
  22. package/docs/components/forms-and-dialogs.md +61 -0
  23. package/docs/components/menus.md +85 -1
  24. package/docs/components/shell.md +37 -0
  25. package/docs/components/tiles.md +37 -0
  26. package/package.json +1 -1
  27. package/src/charts/plot_config_editor.js +125 -29
  28. package/src/tiles/tile_base.js +48 -2
  29. package/src/tiles/tile_grid.js +42 -1
  30. package/src/tiling/kind_taxonomy.js +45 -0
  31. package/src/tiling/wm.js +86 -11
  32. package/src/ui/components/category_picker.js +556 -0
  33. package/src/ui/components/computing_status_window.js +3 -0
  34. package/src/ui/components/confirm_dialog.js +3 -0
  35. package/src/ui/components/managed_window.js +204 -9
  36. package/src/ui/components/wizard.js +4 -1
  37. package/widgets.js +2 -1
  38. package/dist/chunk-MADMGRX2.js.map +0 -7
  39. /package/dist/{chunk-2PM6ZMNS.js.map → chunk-2Z2ENHR3.js.map} +0 -0
  40. /package/dist/{chunk-AD7FIA3Z.js.map → chunk-7JI7HHSY.js.map} +0 -0
  41. /package/dist/{chunk-TLIV6QSU.js.map → chunk-7OL6F2AM.js.map} +0 -0
  42. /package/dist/{chunk-OEG6NPAN.js.map → chunk-XJNADRGR.js.map} +0 -0
package/dist/charts.js CHANGED
@@ -55,17 +55,17 @@ import {
55
55
  strideIndices,
56
56
  uid,
57
57
  updateChart
58
- } from "./chunk-TLIV6QSU.js";
58
+ } from "./chunk-7OL6F2AM.js";
59
59
  import {
60
60
  AutocompleteField,
61
61
  createRafResizeObserver
62
- } from "./chunk-2PM6ZMNS.js";
62
+ } from "./chunk-2Z2ENHR3.js";
63
63
  import {
64
64
  ColorField,
65
65
  ManagedWindow,
66
66
  ToggleField,
67
67
  selectBox
68
- } from "./chunk-MADMGRX2.js";
68
+ } from "./chunk-PGZ4EHSE.js";
69
69
  import "./chunk-HNU6MM2B.js";
70
70
  import "./chunk-N7HC3ADV.js";
71
71
  import "./chunk-WUFLGETN.js";
@@ -758,10 +758,27 @@ function removeButton(title, onClick) {
758
758
  b.appendChild(el("span", "material-symbols-outlined", "close"));
759
759
  return b;
760
760
  }
761
- function field(label, control) {
761
+ var hintCount = 0;
762
+ function field(label, control, { hint = null } = {}) {
762
763
  const single = control.matches("input, select, textarea");
763
- const row = el(single ? "label" : "div", "twm-plot-config__field");
764
- row.append(el("span", "twm-plot-config__label", label), control);
764
+ const hinted = hint != null && hint !== "";
765
+ if (!hinted) {
766
+ const row2 = el(single ? "label" : "div", "twm-plot-config__field");
767
+ row2.append(el("span", "twm-plot-config__label", label), control);
768
+ return row2;
769
+ }
770
+ const row = el("div", "twm-plot-config__field twm-plot-config__field--hinted");
771
+ const text = el(single ? "label" : "span", "twm-plot-config__label", label);
772
+ const note = el("span", "twm-plot-config__hint", hint);
773
+ note.id = `twm-plot-config-hint-${++hintCount}`;
774
+ if (single) {
775
+ if (!control.id) control.id = `${note.id}-control`;
776
+ text.htmlFor = control.id;
777
+ }
778
+ const target = single ? control : control.querySelector("input, select, textarea") ?? control;
779
+ const describedBy = target.getAttribute("aria-describedby");
780
+ target.setAttribute("aria-describedby", describedBy ? `${describedBy} ${note.id}` : note.id);
781
+ row.append(text, control, note);
765
782
  return row;
766
783
  }
767
784
  function textInput(value, onSet, { placeholder = "", label = null } = {}) {
@@ -920,7 +937,7 @@ function renderPlotConfigEditor(container, config, options = {}) {
920
937
  node.classList.add("twm-plot-config__picker");
921
938
  return node;
922
939
  }
923
- function colorField(value, onSet, label) {
940
+ function colorField(value, onSet, label, keep = track) {
924
941
  const f = new ColorField({
925
942
  value: value ?? "",
926
943
  label,
@@ -931,7 +948,7 @@ function renderPlotConfigEditor(container, config, options = {}) {
931
948
  }
932
949
  }
933
950
  });
934
- track(() => f.dispose());
951
+ keep(() => f.dispose());
935
952
  return f.render();
936
953
  }
937
954
  function toggle(label, checked, onSet) {
@@ -1154,60 +1171,113 @@ function renderPlotConfigEditor(container, config, options = {}) {
1154
1171
  }
1155
1172
  function seriesRow(sp, axis, s, overlaySources) {
1156
1173
  const row = el("div", "twm-plot-config__series");
1157
- const main = el("div", "twm-plot-config__series-main");
1158
- main.append(
1174
+ const head = el("div", "twm-plot-config__series-head");
1175
+ head.append(
1159
1176
  seriesPicker(s, "variable", "series", sp, "Series"),
1160
1177
  textInput(s.label, (v) => {
1161
1178
  s.label = v;
1162
1179
  notify();
1163
1180
  }, { placeholder: "Legend label", label: "Legend label" }),
1164
- colorField(s.color, (v) => {
1181
+ removeButton("Remove series", () => {
1182
+ const i = axis.series.indexOf(s);
1183
+ if (i >= 0) axis.series.splice(i, 1);
1184
+ renderBody();
1185
+ notify();
1186
+ })
1187
+ );
1188
+ const fields = el("div", "twm-plot-config__series-fields");
1189
+ fields.append(
1190
+ field("Colour", colorField(s.color, (v) => {
1165
1191
  if (v) s.color = v;
1166
1192
  else delete s.color;
1167
- }, "Colour"),
1168
- numberInput(
1193
+ }, "Colour")),
1194
+ field("Width", numberInput(
1169
1195
  s.lineWidth ?? 2,
1170
1196
  (v) => {
1171
1197
  s.lineWidth = v ?? 2;
1172
1198
  notify();
1173
1199
  },
1174
1200
  { placeholder: "2", label: "Line width", min: 1, max: 10, step: 1 }
1175
- ),
1176
- select(DASHES, s.lineStyle ?? "solid", (v) => {
1201
+ )),
1202
+ field("Dash", select(DASHES, s.lineStyle ?? "solid", (v) => {
1177
1203
  s.lineStyle = v;
1178
1204
  notify();
1179
- }, { label: "Dash" }),
1180
- textInput(
1205
+ }, { label: "Dash" })),
1206
+ field("Stack group", textInput(
1181
1207
  s.stackGroup,
1182
1208
  (v) => {
1183
1209
  s.stackGroup = v || null;
1184
1210
  notify();
1185
1211
  },
1186
- { placeholder: "Stack group", label: "Stack group" }
1187
- ),
1188
- removeButton("Remove series", () => {
1189
- const i = axis.series.indexOf(s);
1190
- if (i >= 0) axis.series.splice(i, 1);
1191
- renderBody();
1192
- notify();
1193
- })
1212
+ { placeholder: "None", label: "Stack group" }
1213
+ ))
1194
1214
  );
1195
- row.appendChild(main);
1196
- if (opts.extraSeriesFields) {
1197
- const extra = el("div", "twm-plot-config__series-extra");
1198
- row.appendChild(extra);
1199
- const handle = opts.extraSeriesFields(extra, s, { subplot: sp, axis, onChange: notify });
1200
- if (typeof handle?.dispose === "function") track(() => handle.dispose());
1201
- }
1202
- if (opts.overlaySources) row.appendChild(overlayEditor(s, overlaySources));
1215
+ if (opts.extraSeriesFields) fields.appendChild(extraFields(sp, axis, s));
1216
+ if (opts.overlaySources) fields.appendChild(overlayEditor(s, overlaySources));
1217
+ row.append(head, fields);
1203
1218
  return row;
1204
1219
  }
1220
+ const warn = (...args) => opts.logger?.warn ? opts.logger.warn(...args) : console.warn(...args);
1221
+ function extraFields(sp, axis, s) {
1222
+ const extra = el("div", "twm-plot-config__series-extra");
1223
+ const result = opts.extraSeriesFields(extra, s, { subplot: sp, axis, onChange: notify, field });
1224
+ if (!Array.isArray(result)) {
1225
+ if (typeof result?.dispose === "function") track(() => result.dispose());
1226
+ return extra;
1227
+ }
1228
+ for (const spec of result) {
1229
+ const label = spec?.label;
1230
+ let control = null;
1231
+ if (typeof label !== "string") {
1232
+ warn("[plot config editor] an extraSeriesFields spec has no label; skipped", spec);
1233
+ continue;
1234
+ }
1235
+ if (spec.control != null) {
1236
+ if (!(spec.control instanceof Element)) {
1237
+ warn("[plot config editor] an extraSeriesFields spec control is not an Element; skipped", spec);
1238
+ continue;
1239
+ }
1240
+ control = spec.control;
1241
+ } else if (typeof spec.render === "function") {
1242
+ control = el("div", "twm-plot-config__slot");
1243
+ try {
1244
+ const handle = spec.render(control);
1245
+ if (typeof handle?.dispose === "function") track(() => handle.dispose());
1246
+ } catch (error) {
1247
+ warn("[plot config editor] an extraSeriesFields spec failed to render; skipped", error);
1248
+ continue;
1249
+ }
1250
+ } else {
1251
+ warn("[plot config editor] an extraSeriesFields spec has neither control nor render; skipped", spec);
1252
+ continue;
1253
+ }
1254
+ extra.appendChild(field(label, control, { hint: spec.hint }));
1255
+ }
1256
+ return extra;
1257
+ }
1205
1258
  function overlayEditor(s, overlaySources) {
1206
1259
  const wrap = el("div", "twm-plot-config__overlay");
1207
1260
  const head = el("div", "twm-plot-config__overlay-source", "Loading overlay sources\u2026");
1208
1261
  const details = el("div", "twm-plot-config__overlay-fields");
1209
1262
  wrap.append(head, details);
1263
+ let detailDisposers = [];
1264
+ const disposeDetails = () => {
1265
+ const fns = detailDisposers;
1266
+ detailDisposers = [];
1267
+ for (const fn of fns) {
1268
+ try {
1269
+ fn();
1270
+ } catch (error) {
1271
+ opts.logger?.warn?.("[plot config editor] a field failed to dispose", error);
1272
+ }
1273
+ }
1274
+ };
1275
+ track(disposeDetails);
1276
+ const keep = (fn) => {
1277
+ detailDisposers.push(fn);
1278
+ };
1210
1279
  const drawDetails = () => {
1280
+ disposeDetails();
1211
1281
  details.replaceChildren();
1212
1282
  const ov = s.overlay;
1213
1283
  if (!ov) return;
@@ -1223,7 +1293,7 @@ function renderPlotConfigEditor(container, config, options = {}) {
1223
1293
  field("Colour", colorField(ov.color, (v) => {
1224
1294
  if (v) ov.color = v;
1225
1295
  else delete ov.color;
1226
- }, "Overlay colour")),
1296
+ }, "Overlay colour", keep)),
1227
1297
  field("Dash", select(DASHES, ov.lineStyle ?? "dashed", (v) => {
1228
1298
  ov.lineStyle = v;
1229
1299
  notify();