@xenosystem/blocks 0.13.12 → 0.13.14

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.
@@ -9,11 +9,10 @@ import {
9
9
  import {
10
10
  ChevronGlyph,
11
11
  ICONS,
12
- PlugGlyph,
13
12
  RefreshGlyph,
14
13
  SortAscGlyph,
15
14
  SortDescGlyph
16
- } from "../chunk-5BVZMAD2.js";
15
+ } from "../chunk-PI5WOATA.js";
17
16
  import "../chunk-2KG3PWR4.js";
18
17
 
19
18
  // src/data/table/panel.ts
@@ -195,8 +194,8 @@ function moveCell(from, delta, bounds) {
195
194
  }
196
195
 
197
196
  // src/data/table/numeric.ts
198
- function parseNumeric(text4) {
199
- const trimmed = String(text4).trim();
197
+ function parseNumeric(text5) {
198
+ const trimmed = String(text5).trim();
200
199
  if (trimmed.length === 0) return { ok: false, reason: "empty" };
201
200
  const match = /^[+-]?(\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/.exec(trimmed);
202
201
  if (!match) return { ok: false, reason: "nan" };
@@ -550,11 +549,11 @@ var TableController = class {
550
549
  return true;
551
550
  }
552
551
  /** Update the in-flight draft. Emits `editPreview` only when `livePreview` is on. */
553
- updateDraft(text4) {
552
+ updateDraft(text5) {
554
553
  if (!this.editing) return;
555
- this.editing = { ...this.editing, draft: text4 };
554
+ this.editing = { ...this.editing, draft: text5 };
556
555
  if (this.livePreview) {
557
- const parsed = this.parseDraft(this.editing.columnId, text4);
556
+ const parsed = this.parseDraft(this.editing.columnId, text5);
558
557
  if (parsed.ok) {
559
558
  this.host.emit("editPreview", this.buildEdit(this.editing, parsed.value));
560
559
  }
@@ -606,12 +605,12 @@ var TableController = class {
606
605
  };
607
606
  }
608
607
  /** Parse a draft according to the column's declared type. */
609
- parseDraft(columnId, text4) {
608
+ parseDraft(columnId, text5) {
610
609
  const column = this.columnById(columnId);
611
- const trimmed = text4.trim();
610
+ const trimmed = text5.trim();
612
611
  if (column?.type === "number" || column?.type === "integer" || column?.type === "duration") {
613
612
  if (trimmed === "") return { ok: true, value: null };
614
- const parsed = parseNumeric(text4);
613
+ const parsed = parseNumeric(text5);
615
614
  if (!parsed.ok) return { ok: false, reason: parsed.reason };
616
615
  return { ok: true, value: normalizeNumeric(parsed.value, constraintsOfColumn(column)) };
617
616
  }
@@ -628,7 +627,7 @@ var TableController = class {
628
627
  value: trimmed === "" ? [] : trimmed.split(",").map((part) => part.trim()).filter(Boolean)
629
628
  };
630
629
  }
631
- return { ok: true, value: trimmed === "" ? null : text4 };
630
+ return { ok: true, value: trimmed === "" ? null : text5 };
632
631
  }
633
632
  rowById(rowId) {
634
633
  return this.result?.rows.find((r) => r.id === rowId);
@@ -2375,16 +2374,16 @@ function chartRuntimeComponents(controller, options) {
2375
2374
  function ChartPanelView({ controller, options, emptyHint }) {
2376
2375
  useSyncExternalStore2(controller.subscribe, controller.getState, controller.getState);
2377
2376
  const view = chartViewState(controller, { emptyHint });
2378
- const ui4 = (intent) => applyChartUi(controller, intent);
2377
+ const ui5 = (intent) => applyChartUi(controller, intent);
2379
2378
  return /* @__PURE__ */ jsxs2(Column, { children: [
2380
2379
  /* @__PURE__ */ jsx2(
2381
2380
  Toolbar2,
2382
2381
  {
2383
- left: /* @__PURE__ */ jsx2(SegmentedControl2, { size: "sm", label: "Chart type", options: view.types, value: view.type, onChange: (type) => ui4({ kind: "type", type }) }),
2382
+ left: /* @__PURE__ */ jsx2(SegmentedControl2, { size: "sm", label: "Chart type", options: view.types, value: view.type, onChange: (type) => ui5({ kind: "type", type }) }),
2384
2383
  right: /* @__PURE__ */ jsxs2(ToolbarGroup2, { end: true, children: [
2385
2384
  view.partial ? /* @__PURE__ */ jsx2(Badge2, { tone: "warning", title: "Some measures have not synced yet.", children: "partial" }) : null,
2386
2385
  view.aggregating ? /* @__PURE__ */ jsx2(Badge2, { tone: "warning", title: view.aggregatingHint, children: "aggregating" }) : null,
2387
- /* @__PURE__ */ jsx2(IconButton2, { icon: /* @__PURE__ */ jsx2(DownloadGlyph, {}), label: "Export chart", onClick: () => ui4({ kind: "export" }) })
2386
+ /* @__PURE__ */ jsx2(IconButton2, { icon: /* @__PURE__ */ jsx2(DownloadGlyph, {}), label: "Export chart", onClick: () => ui5({ kind: "export" }) })
2388
2387
  ] })
2389
2388
  }
2390
2389
  ),
@@ -3088,12 +3087,12 @@ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
3088
3087
  function MetricsPanelView({ controller, ...options }) {
3089
3088
  useSyncExternalStore3(controller.subscribe, controller.getState, controller.getState);
3090
3089
  const view = metricsViewState(controller, options);
3091
- const ui4 = (intent) => applyMetricsUi(controller, intent);
3090
+ const ui5 = (intent) => applyMetricsUi(controller, intent);
3092
3091
  return /* @__PURE__ */ jsxs3(Column2, { children: [
3093
3092
  view.hasRanges ? /* @__PURE__ */ jsx3(
3094
3093
  Toolbar3,
3095
3094
  {
3096
- left: /* @__PURE__ */ jsx3(SegmentedControl3, { size: "sm", label: "Range", options: view.ranges, value: view.rangeId, onChange: (rangeId) => ui4({ kind: "range", rangeId }) }),
3095
+ left: /* @__PURE__ */ jsx3(SegmentedControl3, { size: "sm", label: "Range", options: view.ranges, value: view.rangeId, onChange: (rangeId) => ui5({ kind: "range", rangeId }) }),
3097
3096
  right: view.partial ? /* @__PURE__ */ jsx3(Badge3, { tone: "warning", title: view.partialHint, children: "partial" }) : null
3098
3097
  }
3099
3098
  ) : null,
@@ -3111,7 +3110,7 @@ function MetricsPanelView({ controller, ...options }) {
3111
3110
  tile.partial ? /* @__PURE__ */ jsx3(Text, { role: "meta", children: view.partialHint }) : null,
3112
3111
  tile.hasSpark ? /* @__PURE__ */ jsx3(Sparkline, { data: tile.spark, label: tile.sparkLabel }) : null
3113
3112
  ] }),
3114
- onActivate: () => ui4({ kind: "activate", metricId: tile.id })
3113
+ onActivate: () => ui5({ kind: "activate", metricId: tile.id })
3115
3114
  },
3116
3115
  tile.id
3117
3116
  )) }) }) : null,
@@ -3313,7 +3312,7 @@ function emptyFilterGroup() {
3313
3312
  function offerableFilterOps(column, sourceOps = []) {
3314
3313
  const common = ["eq", "ne", "isEmpty", "isNotEmpty", "in", "notIn"];
3315
3314
  const ordered = ["gt", "gte", "lt", "lte", "between"];
3316
- const text4 = ["contains", "notContains", "startsWith", "endsWith"];
3315
+ const text5 = ["contains", "notContains", "startsWith", "endsWith"];
3317
3316
  const temporal = ["relative"];
3318
3317
  let ops = [...common];
3319
3318
  switch (column?.type) {
@@ -3331,10 +3330,10 @@ function offerableFilterOps(column, sourceOps = []) {
3331
3330
  case "url":
3332
3331
  case "select":
3333
3332
  case "multiselect":
3334
- ops = [...ops, ...text4];
3333
+ ops = [...ops, ...text5];
3335
3334
  break;
3336
3335
  default:
3337
- ops = [...ops, ...text4, ...ordered];
3336
+ ops = [...ops, ...text5, ...ordered];
3338
3337
  }
3339
3338
  if (sourceOps.length === 0) return ops;
3340
3339
  return ops.filter((op) => sourceOps.includes(op));
@@ -4246,7 +4245,7 @@ var COMBINATORS2 = [{ value: "and", label: "All" }, { value: "or", label: "Any"
4246
4245
  function FieldsPanelView({ controller, showStats, manualApply }) {
4247
4246
  useSyncExternalStore4(controller.subscribe, controller.getState, controller.getState);
4248
4247
  const view = fieldsViewState(controller, { showStats, manualApply });
4249
- const ui4 = (intent) => applyFieldsUi(controller, intent);
4248
+ const ui5 = (intent) => applyFieldsUi(controller, intent);
4250
4249
  if (view.noColumns) {
4251
4250
  return /* @__PURE__ */ jsx4(EmptyState4, { title: "No fields", hint: "Connect a source \u2014 its columns appear here, ready to drop onto a shelf." });
4252
4251
  }
@@ -4256,8 +4255,8 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
4256
4255
  {
4257
4256
  left: view.sampled ? /* @__PURE__ */ jsx4(Badge4, { tone: "warning", title: view.sampleWarning, children: "sampled schema" }) : null,
4258
4257
  right: /* @__PURE__ */ jsxs4(ToolbarGroup3, { end: true, children: [
4259
- /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui4({ kind: "autoAssign" }), children: "Auto-assign" }),
4260
- view.manualApply ? /* @__PURE__ */ jsx4(TextButton, { strong: true, disabled: view.applyDisabled, onClick: () => ui4({ kind: "apply" }), children: "Apply" }) : null
4258
+ /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui5({ kind: "autoAssign" }), children: "Auto-assign" }),
4259
+ view.manualApply ? /* @__PURE__ */ jsx4(TextButton, { strong: true, disabled: view.applyDisabled, onClick: () => ui5({ kind: "apply" }), children: "Apply" }) : null
4261
4260
  ] })
4262
4261
  }
4263
4262
  ),
@@ -4269,7 +4268,7 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
4269
4268
  meta: column.role,
4270
4269
  selected: column.focused,
4271
4270
  trailing: column.stat ? /* @__PURE__ */ jsx4(Badge4, { title: column.statTitle, children: column.stat }) : null,
4272
- onClick: () => ui4({ kind: "focus", columnId: column.id })
4271
+ onClick: () => ui5({ kind: "focus", columnId: column.id })
4273
4272
  },
4274
4273
  column.id
4275
4274
  )) }) }),
@@ -4281,11 +4280,11 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
4281
4280
  label: entry.label,
4282
4281
  dimmed: entry.suggested,
4283
4282
  meta: /* @__PURE__ */ jsxs4(Fragment2, { children: [
4284
- entry.aggregated ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Aggregate", options: entry.aggregates, value: entry.fn, onChange: (fn) => ui4({ kind: "aggregate", shelfId: entry.shelfId, columnId: entry.columnId, fn }) }) : null,
4285
- entry.sortable ? /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui4({ kind: "direction", shelfId: entry.shelfId, columnId: entry.columnId }), children: entry.direction }) : null,
4283
+ entry.aggregated ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Aggregate", options: entry.aggregates, value: entry.fn, onChange: (fn) => ui5({ kind: "aggregate", shelfId: entry.shelfId, columnId: entry.columnId, fn }) }) : null,
4284
+ entry.sortable ? /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui5({ kind: "direction", shelfId: entry.shelfId, columnId: entry.columnId }), children: entry.direction }) : null,
4286
4285
  entry.granularity ? /* @__PURE__ */ jsx4(Badge4, { children: entry.granularity }) : null
4287
4286
  ] }),
4288
- trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: entry.removeLabel, onClick: () => ui4({ kind: "remove", shelfId: entry.shelfId, columnId: entry.columnId }) })
4287
+ trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: entry.removeLabel, onClick: () => ui5({ kind: "remove", shelfId: entry.shelfId, columnId: entry.columnId }) })
4289
4288
  },
4290
4289
  entry.columnId
4291
4290
  )) }) : null
@@ -4296,15 +4295,15 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
4296
4295
  title: "Filters",
4297
4296
  flush: true,
4298
4297
  badge: view.hasFilters ? /* @__PURE__ */ jsx4(Badge4, { children: view.filterCount }) : null,
4299
- actions: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(PlusGlyph, { size: 11 }), label: "Add filter", onClick: () => ui4({ kind: "addFilter" }) }),
4298
+ actions: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(PlusGlyph, { size: 11 }), label: "Add filter", onClick: () => ui5({ kind: "addFilter" }) }),
4300
4299
  children: [
4301
4300
  view.noFilters ? /* @__PURE__ */ jsx4(Note, { children: "No filters. Everything passes." }) : null,
4302
4301
  view.hasFilters ? /* @__PURE__ */ jsx4(RowList, { children: view.filters.map((filter) => /* @__PURE__ */ jsx4(
4303
4302
  Row,
4304
4303
  {
4305
4304
  label: filter.label,
4306
- meta: filter.leaf ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Operator", options: filter.ops, value: filter.op, onChange: (op) => ui4({ kind: "filterOp", index: filter.index, op }) }) : null,
4307
- trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: filter.removeLabel, onClick: () => ui4({ kind: "removeFilter", index: filter.index }) })
4305
+ meta: filter.leaf ? /* @__PURE__ */ jsx4(Select, { size: "sm", label: "Operator", options: filter.ops, value: filter.op, onChange: (op) => ui5({ kind: "filterOp", index: filter.index, op }) }) : null,
4306
+ trailing: /* @__PURE__ */ jsx4(IconButton3, { size: "sm", icon: /* @__PURE__ */ jsx4(CloseGlyph, { size: 11 }), label: filter.removeLabel, onClick: () => ui5({ kind: "removeFilter", index: filter.index }) })
4308
4307
  },
4309
4308
  filter.key
4310
4309
  )) }) : null,
@@ -4312,8 +4311,8 @@ function FieldsPanelView({ controller, showStats, manualApply }) {
4312
4311
  Toolbar4,
4313
4312
  {
4314
4313
  divided: false,
4315
- left: /* @__PURE__ */ jsx4(SegmentedControl4, { size: "sm", label: "Combinator", options: COMBINATORS2, value: view.combinator, onChange: (combinator) => ui4({ kind: "combinator", combinator }) }),
4316
- right: /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui4({ kind: "addGroup" }), children: "+ group" })
4314
+ left: /* @__PURE__ */ jsx4(SegmentedControl4, { size: "sm", label: "Combinator", options: COMBINATORS2, value: view.combinator, onChange: (combinator) => ui5({ kind: "combinator", combinator }) }),
4315
+ right: /* @__PURE__ */ jsx4(TextButton, { onClick: () => ui5({ kind: "addGroup" }), children: "+ group" })
4317
4316
  }
4318
4317
  )
4319
4318
  ]
@@ -4604,6 +4603,8 @@ var ConnectorsController = class {
4604
4603
  lastQueries = /* @__PURE__ */ new Map();
4605
4604
  selectedId = null;
4606
4605
  form = null;
4606
+ /** The form's draft values. In the controller, not React state, so the declaration can bind them — and cleared with the form. */
4607
+ draft = {};
4607
4608
  /** Newest outstanding request per `(connectionId, requestorPanelId)`. */
4608
4609
  outstanding = /* @__PURE__ */ new Map();
4609
4610
  /** In-flight executions, keyed by cache key — the single-flight map. */
@@ -4778,6 +4779,17 @@ var ConnectorsController = class {
4778
4779
  /** The host asks for a credential. The panel renders the descriptor; it knows no platform names. */
4779
4780
  requireCredential(spec) {
4780
4781
  this.form = spec;
4782
+ this.draft = {};
4783
+ this.notify();
4784
+ }
4785
+ /** The draft as typed so far. Never emitted except through {@link submitCredential}. */
4786
+ getCredentialDraft() {
4787
+ return this.draft;
4788
+ }
4789
+ /** One field of the draft changed. */
4790
+ setCredentialDraft(key, value) {
4791
+ if (!this.form) return;
4792
+ this.draft = { ...this.draft, [key]: value };
4781
4793
  this.notify();
4782
4794
  }
4783
4795
  /**
@@ -4797,6 +4809,7 @@ var ConnectorsController = class {
4797
4809
  };
4798
4810
  this.host.emit("credentialSubmit", submission);
4799
4811
  this.form = null;
4812
+ this.draft = {};
4800
4813
  this.notify();
4801
4814
  return true;
4802
4815
  }
@@ -4804,6 +4817,7 @@ var ConnectorsController = class {
4804
4817
  cancelCredential() {
4805
4818
  if (!this.form) return;
4806
4819
  this.form = null;
4820
+ this.draft = {};
4807
4821
  this.notify();
4808
4822
  }
4809
4823
  /**
@@ -5449,10 +5463,10 @@ function parseJsonPath(path) {
5449
5463
  }
5450
5464
  return steps;
5451
5465
  }
5452
- function findBracketEnd(text4, start) {
5466
+ function findBracketEnd(text5, start) {
5453
5467
  let quote = null;
5454
- for (let i = start + 1; i < text4.length; i += 1) {
5455
- const char = text4[i];
5468
+ for (let i = start + 1; i < text5.length; i += 1) {
5469
+ const char = text5[i];
5456
5470
  if (quote) {
5457
5471
  if (char === "\\") i += 1;
5458
5472
  else if (char === quote) quote = null;
@@ -5876,9 +5890,9 @@ function firstGraphqlError(errors) {
5876
5890
  }
5877
5891
 
5878
5892
  // src/data/connectors/executors/csv.ts
5879
- function sniffDelimiter(text4) {
5893
+ function sniffDelimiter(text5) {
5880
5894
  const candidates = [",", ";", " ", "|"];
5881
- const line = firstLogicalLine(text4);
5895
+ const line = firstLogicalLine(text5);
5882
5896
  let best = ",";
5883
5897
  let bestCount = 0;
5884
5898
  for (const candidate of candidates) {
@@ -5900,21 +5914,21 @@ function sniffDelimiter(text4) {
5900
5914
  }
5901
5915
  return best;
5902
5916
  }
5903
- function firstLogicalLine(text4) {
5917
+ function firstLogicalLine(text5) {
5904
5918
  let inQuotes = false;
5905
- for (let i = 0; i < text4.length; i += 1) {
5906
- const char = text4[i];
5919
+ for (let i = 0; i < text5.length; i += 1) {
5920
+ const char = text5[i];
5907
5921
  if (char === '"') {
5908
- if (inQuotes && text4[i + 1] === '"') i += 1;
5922
+ if (inQuotes && text5[i + 1] === '"') i += 1;
5909
5923
  else inQuotes = !inQuotes;
5910
5924
  } else if ((char === "\n" || char === "\r") && !inQuotes) {
5911
- return text4.slice(0, i);
5925
+ return text5.slice(0, i);
5912
5926
  }
5913
5927
  }
5914
- return text4;
5928
+ return text5;
5915
5929
  }
5916
- function parseCsv(text4, options = {}) {
5917
- const source = text4.charCodeAt(0) === 65279 ? text4.slice(1) : text4;
5930
+ function parseCsv(text5, options = {}) {
5931
+ const source = text5.charCodeAt(0) === 65279 ? text5.slice(1) : text5;
5918
5932
  const delimiter = options.delimiter && options.delimiter.length > 0 ? options.delimiter : sniffDelimiter(source);
5919
5933
  const quote = options.quote && options.quote.length > 0 ? options.quote : '"';
5920
5934
  const hasHeader = options.hasHeader ?? true;
@@ -5949,17 +5963,17 @@ function dedupe(names) {
5949
5963
  return count === 0 ? name : `${name}_${count + 1}`;
5950
5964
  });
5951
5965
  }
5952
- function scanRecords(text4, delimiter, quote) {
5966
+ function scanRecords(text5, delimiter, quote) {
5953
5967
  const records = [];
5954
5968
  let fields = [];
5955
5969
  let field = "";
5956
5970
  let inQuotes = false;
5957
5971
  let i = 0;
5958
- while (i < text4.length) {
5959
- const char = text4[i];
5972
+ while (i < text5.length) {
5973
+ const char = text5[i];
5960
5974
  if (inQuotes) {
5961
5975
  if (char === quote) {
5962
- if (text4[i + 1] === quote) {
5976
+ if (text5[i + 1] === quote) {
5963
5977
  field += quote;
5964
5978
  i += 2;
5965
5979
  continue;
@@ -5977,7 +5991,7 @@ function scanRecords(text4, delimiter, quote) {
5977
5991
  i += 1;
5978
5992
  continue;
5979
5993
  }
5980
- if (text4.startsWith(delimiter, i)) {
5994
+ if (text5.startsWith(delimiter, i)) {
5981
5995
  fields.push(field);
5982
5996
  field = "";
5983
5997
  i += delimiter.length;
@@ -5988,7 +6002,7 @@ function scanRecords(text4, delimiter, quote) {
5988
6002
  records.push(fields);
5989
6003
  fields = [];
5990
6004
  field = "";
5991
- i += char === "\r" && text4[i + 1] === "\n" ? 2 : 1;
6005
+ i += char === "\r" && text5[i + 1] === "\n" ? 2 : 1;
5992
6006
  continue;
5993
6007
  }
5994
6008
  field += char;
@@ -6554,18 +6568,26 @@ var connectorsManifest = {
6554
6568
  };
6555
6569
 
6556
6570
  // src/data/connectors/react/ConnectorsPanelView.tsx
6557
- import { useState as useState2, useSyncExternalStore as useSyncExternalStore5 } from "react";
6571
+ import { useSyncExternalStore as useSyncExternalStore5 } from "react";
6558
6572
  import {
6559
6573
  Badge as Badge5,
6574
+ Code,
6575
+ Column as Column4,
6560
6576
  EmptyState as EmptyState5,
6561
6577
  Field,
6562
6578
  FieldGroup,
6563
6579
  IconButton as IconButton4,
6580
+ Input,
6581
+ Link,
6582
+ Note as Note2,
6564
6583
  Row as Row2,
6565
6584
  RowList as RowList2,
6566
6585
  ScrollArea as ScrollArea4,
6586
+ Select as Select2,
6567
6587
  StatusBar as StatusBar5,
6588
+ Text as Text2,
6568
6589
  TextButton as TextButton2,
6590
+ Toggle,
6569
6591
  Toolbar as Toolbar5,
6570
6592
  ToolbarGroup as ToolbarGroup4
6571
6593
  } from "@xenosystem/components/chrome";
@@ -6631,183 +6653,254 @@ function credentialSpecProblem(spec) {
6631
6653
  return null;
6632
6654
  }
6633
6655
 
6634
- // src/data/connectors/react/ConnectorsPanelView.tsx
6635
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
6636
- var TONE = {
6637
- unknown: "neutral",
6638
- ok: "success",
6639
- degraded: "warning",
6640
- unconfigured: "info",
6641
- unsupported: "warning",
6642
- error: "error",
6643
- expired: "warning"
6644
- };
6645
- function ConnectorsPanelView({
6646
- controller,
6647
- emptyHint
6648
- }) {
6649
- const state = useSyncExternalStore5(controller.subscribe, controller.getState, controller.getState);
6650
- if (state.form) {
6651
- return /* @__PURE__ */ jsx5(CredentialForm, { controller });
6656
+ // src/data/connectors/declaration.ts
6657
+ var TONE = { unknown: "neutral", ok: "success", degraded: "warning", unconfigured: "info", unsupported: "warning", error: "error", expired: "warning" };
6658
+ function connectorsViewState(c, options = {}) {
6659
+ const s = c.getState();
6660
+ const form = s.form;
6661
+ const draft = c.getCredentialDraft();
6662
+ const problem = form ? credentialSpecProblem(form) : null;
6663
+ const shown = form && !problem ? visibleFields(form, draft) : [];
6664
+ const errors = form && !problem ? validateCredentialDraft(form, draft) : {};
6665
+ return {
6666
+ listing: !form,
6667
+ sources: form ? [] : s.connections.map(({ connection, status }) => ({
6668
+ id: connection.id,
6669
+ name: connection.name,
6670
+ kind: connection.kind,
6671
+ selected: connection.id === s.selectedId,
6672
+ disabled: status.health === "unsupported",
6673
+ title: status.message,
6674
+ health: status.health,
6675
+ tone: TONE[status.health] ?? "neutral"
6676
+ })),
6677
+ empty: !form && s.connections.length === 0,
6678
+ emptyHint: options.emptyHint ?? "Paste CSV or JSON to start with an inline source \u2014 no setup needed.",
6679
+ listed: !form && s.connections.length > 0,
6680
+ countLabel: `${s.connections.length} source${s.connections.length === 1 ? "" : "s"}`,
6681
+ busyLabel: s.busy.length > 0 ? "querying\u2026" : void 0,
6682
+ form: !!form,
6683
+ formTitle: form?.title ?? "",
6684
+ formBroken: !!form && !!problem,
6685
+ formProblem: problem ?? void 0,
6686
+ formReady: !!form && !problem,
6687
+ formMessage: form?.message,
6688
+ redirectUri: form?.redirectUri,
6689
+ fields: shown.map((field) => {
6690
+ const kind = field.type === "textarea" ? "textarea" : field.type;
6691
+ return {
6692
+ key: field.key,
6693
+ label: field.label,
6694
+ hint: errors[field.key] ?? field.description,
6695
+ kind,
6696
+ isText: kind === "text" || kind === "password" || kind === "number" || kind === "textarea",
6697
+ isSelect: kind === "select",
6698
+ isBoolean: kind === "boolean",
6699
+ inputType: kind === "password" ? "password" : kind === "number" ? "number" : "text",
6700
+ text: String(draft[field.key] ?? ""),
6701
+ checked: draft[field.key] === true,
6702
+ placeholder: field.placeholder,
6703
+ options: field.options ?? []
6704
+ };
6705
+ }),
6706
+ docsUrl: form?.docsUrl,
6707
+ submitDisabled: Object.keys(errors).length > 0
6708
+ };
6709
+ }
6710
+ function applyConnectorsUi(c, intent) {
6711
+ switch (intent.kind) {
6712
+ case "refreshAll":
6713
+ void c.refreshAll();
6714
+ break;
6715
+ case "select":
6716
+ c.select(intent.id);
6717
+ break;
6718
+ case "field":
6719
+ c.setCredentialDraft(intent.key, intent.value);
6720
+ break;
6721
+ case "cancel":
6722
+ c.cancelCredential();
6723
+ break;
6724
+ case "submit": {
6725
+ const form = c.getState().form;
6726
+ if (form) c.submitCredential(pruneHiddenValues(form, c.getCredentialDraft()));
6727
+ break;
6728
+ }
6652
6729
  }
6653
- return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }, children: [
6654
- /* @__PURE__ */ jsx5(
6655
- Toolbar5,
6730
+ }
6731
+ var connectorsViewManifest = {
6732
+ id: connectorsManifest.id,
6733
+ version: "1.0.0",
6734
+ title: "Connectors",
6735
+ category: "data",
6736
+ layout: { slot: "side" },
6737
+ inputs: [{ id: "view", type: "object", label: "View state", description: "The ConnectorsViewModel the runtime derives from the controller on every draw." }],
6738
+ outputs: [{ id: "ui", type: "object", label: "UI intent", description: "{ kind, \u2026 } \u2014 applied by the runtime to the controller." }],
6739
+ commands: []
6740
+ };
6741
+ var EMPTY4 = { listing: true, sources: [], empty: true, emptyHint: "Paste CSV or JSON to start with an inline source \u2014 no setup needed.", listed: false, countLabel: "0 sources", form: false, formTitle: "", formBroken: false, formReady: false, fields: [], submitDisabled: true };
6742
+ var BEHAVIOURS4 = {
6743
+ "data/connectorsPanelView": (inputs) => inputs.view ?? EMPTY4
6744
+ };
6745
+ var CONNECTORS_RUNTIME_UNITS = [];
6746
+ var text4 = (b) => ({ component: "text", props: { text: b } });
6747
+ var ui4 = (kind, fields = {}) => ({ emit: "ui", value: { object: { kind: { value: kind }, ...fields } } });
6748
+ var CONNECTORS_DECLARATION = {
6749
+ format: "xeno.block@1",
6750
+ manifest: connectorsViewManifest,
6751
+ behaviour: "data/connectorsPanelView",
6752
+ composition: {
6753
+ component: "fragment",
6754
+ children: [
6656
6755
  {
6657
- right: /* @__PURE__ */ jsx5(ToolbarGroup4, { end: true, children: /* @__PURE__ */ jsx5(
6658
- IconButton4,
6756
+ component: "chrome/Column",
6757
+ when: { input: "view.listing" },
6758
+ children: [
6759
+ { component: "chrome/Toolbar", props: { right: { node: { component: "chrome/ToolbarGroup", props: { end: { value: true } }, children: [{ component: "chrome/IconButton", props: { icon: { node: { component: "icons/Refresh" } }, label: { value: "Refresh all" } }, on: { onClick: ui4("refreshAll") } }] } } } },
6760
+ { component: "chrome/EmptyState", when: { input: "view.empty" }, props: { title: { value: "No sources" }, hint: { input: "view.emptyHint" } } },
6659
6761
  {
6660
- icon: /* @__PURE__ */ jsx5(RefreshGlyph, {}),
6661
- label: "Refresh all",
6662
- onClick: () => void controller.refreshAll()
6663
- }
6664
- ) })
6665
- }
6666
- ),
6667
- state.connections.length === 0 ? /* @__PURE__ */ jsx5(
6668
- EmptyState5,
6762
+ component: "chrome/ScrollArea",
6763
+ when: { input: "view.listed" },
6764
+ children: [
6765
+ {
6766
+ component: "chrome/RowList",
6767
+ props: { role: { value: "listbox" }, "aria-label": { value: "Data sources" } },
6768
+ children: [
6769
+ {
6770
+ component: "chrome/Row",
6771
+ each: { input: "view.sources", key: "id" },
6772
+ props: { icon: { node: { component: "icons/Plug" } }, label: { item: "name" }, meta: { item: "kind" }, selected: { item: "selected" }, disabled: { item: "disabled" }, title: { item: "title" }, trailing: { node: { component: "chrome/Badge", props: { tone: { item: "tone" } }, children: [text4({ item: "health" })] } } },
6773
+ on: { onClick: ui4("select", { id: { item: "id" } }) }
6774
+ }
6775
+ ]
6776
+ }
6777
+ ]
6778
+ },
6779
+ { component: "chrome/StatusBar", props: { left: { input: "view.countLabel" }, right: { input: "view.busyLabel" } } }
6780
+ ]
6781
+ },
6669
6782
  {
6670
- title: "No sources",
6671
- hint: emptyHint ?? "Paste CSV or JSON to start with an inline source \u2014 no setup needed."
6783
+ component: "chrome/Column",
6784
+ when: { input: "view.form" },
6785
+ children: [
6786
+ { component: "chrome/Toolbar", props: { left: { node: { component: "chrome/Text", props: { role: { value: "title" } }, children: [text4({ input: "view.formTitle" })] } } } },
6787
+ { component: "chrome/EmptyState", when: { input: "view.formBroken" }, props: { title: { value: "This connection cannot be set up" }, hint: { input: "view.formProblem" } } },
6788
+ {
6789
+ component: "chrome/Toolbar",
6790
+ when: { input: "view.formBroken" },
6791
+ props: { divided: { value: false }, right: { node: { component: "chrome/ToolbarGroup", props: { end: { value: true } }, children: [{ component: "chrome/TextButton", on: { onClick: ui4("cancel") }, children: [text4({ value: "Close" })] }] } } }
6792
+ },
6793
+ {
6794
+ component: "chrome/ScrollArea",
6795
+ when: { input: "view.formReady" },
6796
+ children: [
6797
+ { component: "chrome/Note", when: { input: "view.formMessage" }, children: [text4({ input: "view.formMessage" })] },
6798
+ {
6799
+ component: "fragment",
6800
+ when: { input: "view.redirectUri" },
6801
+ children: [
6802
+ { component: "chrome/Note", children: [text4({ value: "Add this exact redirect URI to the provider:" })] },
6803
+ // VERBATIM. Rendering the real string is what prevents a redirect-URI mismatch.
6804
+ { component: "chrome/Code", props: { variant: { value: "flush" } }, children: [text4({ input: "view.redirectUri" })] }
6805
+ ]
6806
+ },
6807
+ {
6808
+ component: "chrome/FieldGroup",
6809
+ children: [
6810
+ {
6811
+ component: "chrome/Field",
6812
+ each: { input: "view.fields", key: "key" },
6813
+ props: { label: { item: "label" }, hint: { item: "hint" } },
6814
+ children: [
6815
+ { component: "chrome/Input", when: { item: "isText" }, props: { type: { item: "inputType" }, value: { item: "text" }, placeholder: { item: "placeholder" }, autoComplete: { value: "off" }, label: { item: "label" } }, on: { onChange: ui4("field", { key: { item: "key" }, value: { arg: "" } }) } },
6816
+ { component: "chrome/Select", when: { item: "isSelect" }, props: { options: { item: "options" }, value: { item: "text" }, placeholder: { value: "" }, label: { item: "label" } }, on: { onChange: ui4("field", { key: { item: "key" }, value: { arg: "" } }) } },
6817
+ { component: "chrome/Toggle", when: { item: "isBoolean" }, props: { checked: { item: "checked" }, label: { item: "label" } }, on: { onChange: ui4("field", { key: { item: "key" }, value: { arg: "" } }) } }
6818
+ ]
6819
+ }
6820
+ ]
6821
+ },
6822
+ { component: "chrome/Note", when: { input: "view.docsUrl" }, children: [{ component: "chrome/Link", props: { href: { input: "view.docsUrl" } }, children: [text4({ value: "Where do I get this?" })] }] }
6823
+ ]
6824
+ },
6825
+ {
6826
+ component: "chrome/Toolbar",
6827
+ when: { input: "view.formReady" },
6828
+ props: {
6829
+ divided: { value: false },
6830
+ right: {
6831
+ node: {
6832
+ component: "chrome/ToolbarGroup",
6833
+ props: { end: { value: true } },
6834
+ children: [
6835
+ { component: "chrome/TextButton", on: { onClick: ui4("cancel") }, children: [text4({ value: "Cancel" })] },
6836
+ { component: "chrome/TextButton", props: { strong: { value: true }, disabled: { input: "view.submitDisabled" } }, on: { onClick: ui4("submit") }, children: [text4({ value: "Connect" })] }
6837
+ ]
6838
+ }
6839
+ }
6840
+ }
6841
+ }
6842
+ ]
6672
6843
  }
6673
- ) : /* @__PURE__ */ jsx5(ScrollArea4, { children: /* @__PURE__ */ jsx5(RowList2, { role: "listbox", "aria-label": "Data sources", children: state.connections.map(({ connection, status }) => {
6674
- const disabled = status.health === "unsupported";
6675
- return /* @__PURE__ */ jsx5(
6844
+ ]
6845
+ }
6846
+ };
6847
+
6848
+ // src/data/connectors/react/ConnectorsPanelView.tsx
6849
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
6850
+ var PlugGlyph = ICONS["icons/Plug"];
6851
+ var RefreshGlyph2 = ICONS["icons/Refresh"];
6852
+ function ConnectorsPanelView({ controller, emptyHint }) {
6853
+ useSyncExternalStore5(controller.subscribe, controller.getState, controller.getState);
6854
+ const view = connectorsViewState(controller, { emptyHint });
6855
+ const ui5 = (intent) => applyConnectorsUi(controller, intent);
6856
+ return /* @__PURE__ */ jsxs5(Fragment3, { children: [
6857
+ view.listing ? /* @__PURE__ */ jsxs5(Column4, { children: [
6858
+ /* @__PURE__ */ jsx5(Toolbar5, { right: /* @__PURE__ */ jsx5(ToolbarGroup4, { end: true, children: /* @__PURE__ */ jsx5(IconButton4, { icon: /* @__PURE__ */ jsx5(RefreshGlyph2, {}), label: "Refresh all", onClick: () => ui5({ kind: "refreshAll" }) }) }) }),
6859
+ view.empty ? /* @__PURE__ */ jsx5(EmptyState5, { title: "No sources", hint: view.emptyHint }) : null,
6860
+ view.listed ? /* @__PURE__ */ jsx5(ScrollArea4, { children: /* @__PURE__ */ jsx5(RowList2, { role: "listbox", "aria-label": "Data sources", children: view.sources.map((source) => /* @__PURE__ */ jsx5(
6676
6861
  Row2,
6677
6862
  {
6678
6863
  icon: /* @__PURE__ */ jsx5(PlugGlyph, {}),
6679
- label: connection.name,
6680
- meta: connection.kind,
6681
- selected: connection.id === state.selectedId,
6682
- disabled,
6683
- title: status.message,
6684
- onClick: () => controller.select(connection.id),
6685
- trailing: /* @__PURE__ */ jsx5(Badge5, { tone: TONE[status.health], children: status.health })
6864
+ label: source.name,
6865
+ meta: source.kind,
6866
+ selected: source.selected,
6867
+ disabled: source.disabled,
6868
+ title: source.title,
6869
+ trailing: /* @__PURE__ */ jsx5(Badge5, { tone: source.tone, children: source.health }),
6870
+ onClick: () => ui5({ kind: "select", id: source.id })
6686
6871
  },
6687
- connection.id
6688
- );
6689
- }) }) }),
6690
- /* @__PURE__ */ jsx5(
6691
- StatusBar5,
6692
- {
6693
- left: `${state.connections.length} source${state.connections.length === 1 ? "" : "s"}`,
6694
- right: state.busy.length > 0 ? "querying\u2026" : void 0
6695
- }
6696
- )
6697
- ] });
6698
- }
6699
- function CredentialForm({ controller }) {
6700
- const state = useSyncExternalStore5(controller.subscribe, controller.getState, controller.getState);
6701
- const [values, setValues] = useState2({});
6702
- const form = state.form;
6703
- if (!form) return null;
6704
- const problem = credentialSpecProblem(form);
6705
- if (problem) {
6706
- return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }, children: [
6707
- /* @__PURE__ */ jsx5(Toolbar5, { left: /* @__PURE__ */ jsx5("span", { style: { fontSize: 11 }, children: form.title }) }),
6708
- /* @__PURE__ */ jsx5(EmptyState5, { title: "This connection cannot be set up", hint: problem }),
6709
- /* @__PURE__ */ jsx5(
6872
+ source.id
6873
+ )) }) }) : null,
6874
+ /* @__PURE__ */ jsx5(StatusBar5, { left: view.countLabel, right: view.busyLabel })
6875
+ ] }) : null,
6876
+ view.form ? /* @__PURE__ */ jsxs5(Column4, { children: [
6877
+ /* @__PURE__ */ jsx5(Toolbar5, { left: /* @__PURE__ */ jsx5(Text2, { role: "title", children: view.formTitle }) }),
6878
+ view.formBroken ? /* @__PURE__ */ jsx5(EmptyState5, { title: "This connection cannot be set up", hint: view.formProblem }) : null,
6879
+ view.formBroken ? /* @__PURE__ */ jsx5(Toolbar5, { divided: false, right: /* @__PURE__ */ jsx5(ToolbarGroup4, { end: true, children: /* @__PURE__ */ jsx5(TextButton2, { onClick: () => ui5({ kind: "cancel" }), children: "Close" }) }) }) : null,
6880
+ view.formReady ? /* @__PURE__ */ jsxs5(ScrollArea4, { children: [
6881
+ view.formMessage ? /* @__PURE__ */ jsx5(Note2, { children: view.formMessage }) : null,
6882
+ view.redirectUri ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
6883
+ /* @__PURE__ */ jsx5(Note2, { children: "Add this exact redirect URI to the provider:" }),
6884
+ /* @__PURE__ */ jsx5(Code, { variant: "flush", children: view.redirectUri })
6885
+ ] }) : null,
6886
+ /* @__PURE__ */ jsx5(FieldGroup, { children: view.fields.map((field) => /* @__PURE__ */ jsxs5(Field, { label: field.label, hint: field.hint, children: [
6887
+ field.isText ? /* @__PURE__ */ jsx5(Input, { type: field.inputType, value: field.text, placeholder: field.placeholder, autoComplete: "off", label: field.label, onChange: (value) => ui5({ kind: "field", key: field.key, value }) }) : null,
6888
+ field.isSelect ? /* @__PURE__ */ jsx5(Select2, { options: field.options, value: field.text, placeholder: "", label: field.label, onChange: (value) => ui5({ kind: "field", key: field.key, value }) }) : null,
6889
+ field.isBoolean ? /* @__PURE__ */ jsx5(Toggle, { checked: field.checked, label: field.label, onChange: (value) => ui5({ kind: "field", key: field.key, value }) }) : null
6890
+ ] }, field.key)) }),
6891
+ view.docsUrl ? /* @__PURE__ */ jsx5(Note2, { children: /* @__PURE__ */ jsx5(Link, { href: view.docsUrl, children: "Where do I get this?" }) }) : null
6892
+ ] }) : null,
6893
+ view.formReady ? /* @__PURE__ */ jsx5(
6710
6894
  Toolbar5,
6711
6895
  {
6712
6896
  divided: false,
6713
- right: /* @__PURE__ */ jsx5(ToolbarGroup4, { end: true, children: /* @__PURE__ */ jsx5(TextButton2, { onClick: () => controller.cancelCredential(), children: "Close" }) })
6714
- }
6715
- )
6716
- ] });
6717
- }
6718
- const shown = visibleFields(form, values);
6719
- const errors = validateCredentialDraft(form, values);
6720
- const invalid = Object.keys(errors).length > 0;
6721
- return /* @__PURE__ */ jsxs5("div", { style: { display: "flex", flexDirection: "column", height: "100%", minHeight: 0 }, children: [
6722
- /* @__PURE__ */ jsx5(Toolbar5, { left: /* @__PURE__ */ jsx5("span", { style: { fontSize: 11 }, children: form.title }) }),
6723
- /* @__PURE__ */ jsxs5(ScrollArea4, { children: [
6724
- form.message ? /* @__PURE__ */ jsx5("div", { style: { padding: 8, fontSize: 11, opacity: 0.8 }, children: form.message }) : null,
6725
- form.redirectUri ? /* @__PURE__ */ jsxs5("div", { style: { padding: 8, fontSize: 11 }, children: [
6726
- /* @__PURE__ */ jsx5("div", { style: { opacity: 0.7, marginBottom: 4 }, children: "Add this exact redirect URI to the provider:" }),
6727
- /* @__PURE__ */ jsx5(
6728
- "code",
6729
- {
6730
- style: {
6731
- display: "block",
6732
- padding: "4px 6px",
6733
- background: "var(--xeno-canvas)",
6734
- borderRadius: 2,
6735
- userSelect: "all",
6736
- wordBreak: "break-all"
6737
- },
6738
- children: form.redirectUri
6739
- }
6740
- )
6741
- ] }) : null,
6742
- /* @__PURE__ */ jsx5(FieldGroup, { children: shown.map((field) => /* @__PURE__ */ jsx5(Field, { label: field.label, hint: errors[field.key] ?? field.description, children: field.type === "boolean" ? /* @__PURE__ */ jsx5(
6743
- "input",
6744
- {
6745
- type: "checkbox",
6746
- checked: values[field.key] === true,
6747
- onChange: (e) => setValues((v) => ({ ...v, [field.key]: e.target.checked }))
6748
- }
6749
- ) : field.type === "select" ? /* @__PURE__ */ jsxs5(
6750
- "select",
6751
- {
6752
- value: String(values[field.key] ?? ""),
6753
- onChange: (e) => setValues((v) => ({ ...v, [field.key]: e.target.value })),
6754
- children: [
6755
- /* @__PURE__ */ jsx5("option", { value: "" }),
6756
- field.options?.map((o) => /* @__PURE__ */ jsx5("option", { value: o.value, children: o.label }, o.value))
6757
- ]
6897
+ right: /* @__PURE__ */ jsxs5(ToolbarGroup4, { end: true, children: [
6898
+ /* @__PURE__ */ jsx5(TextButton2, { onClick: () => ui5({ kind: "cancel" }), children: "Cancel" }),
6899
+ /* @__PURE__ */ jsx5(TextButton2, { strong: true, disabled: view.submitDisabled, onClick: () => ui5({ kind: "submit" }), children: "Connect" })
6900
+ ] })
6758
6901
  }
6759
- ) : /* @__PURE__ */ jsx5(
6760
- "input",
6761
- {
6762
- type: field.type === "password" ? "password" : "text",
6763
- value: String(values[field.key] ?? ""),
6764
- placeholder: field.placeholder,
6765
- autoComplete: "off",
6766
- onChange: (e) => setValues((v) => ({ ...v, [field.key]: e.target.value })),
6767
- style: {
6768
- width: "100%",
6769
- background: "var(--xeno-canvas)",
6770
- border: "1px solid var(--xeno-border)",
6771
- borderRadius: 2,
6772
- color: "inherit",
6773
- font: "inherit",
6774
- padding: "0 6px",
6775
- height: 20
6776
- }
6777
- }
6778
- ) }, field.key)) }),
6779
- form.docsUrl ? /* @__PURE__ */ jsx5("div", { style: { padding: 8 }, children: /* @__PURE__ */ jsx5("a", { href: form.docsUrl, target: "_blank", rel: "noreferrer", style: { fontSize: 10 }, children: "Where do I get this?" }) }) : null
6780
- ] }),
6781
- /* @__PURE__ */ jsx5(
6782
- Toolbar5,
6783
- {
6784
- divided: false,
6785
- right: /* @__PURE__ */ jsxs5(ToolbarGroup4, { end: true, children: [
6786
- /* @__PURE__ */ jsx5(
6787
- TextButton2,
6788
- {
6789
- onClick: () => {
6790
- setValues({});
6791
- controller.cancelCredential();
6792
- },
6793
- children: "Cancel"
6794
- }
6795
- ),
6796
- /* @__PURE__ */ jsx5(
6797
- TextButton2,
6798
- {
6799
- strong: true,
6800
- disabled: invalid,
6801
- onClick: () => {
6802
- controller.submitCredential(pruneHiddenValues(form, values));
6803
- setValues({});
6804
- },
6805
- children: "Connect"
6806
- }
6807
- )
6808
- ] })
6809
- }
6810
- )
6902
+ ) : null
6903
+ ] }) : null
6811
6904
  ] });
6812
6905
  }
6813
6906
 
@@ -7132,7 +7225,10 @@ export {
7132
7225
  CHART_PANEL_ID,
7133
7226
  CHART_RUNTIME_UNITS,
7134
7227
  CHART_TYPE_LABELS,
7228
+ BEHAVIOURS4 as CONNECTORS_BEHAVIOURS,
7229
+ CONNECTORS_DECLARATION,
7135
7230
  CONNECTORS_PANEL_ID,
7231
+ CONNECTORS_RUNTIME_UNITS,
7136
7232
  ChartController,
7137
7233
  ChartPanelView,
7138
7234
  ChartPlot,
@@ -7167,6 +7263,7 @@ export {
7167
7263
  TableController,
7168
7264
  TablePanelView,
7169
7265
  applyChartUi,
7266
+ applyConnectorsUi,
7170
7267
  applyFieldsUi,
7171
7268
  applyMetricsUi,
7172
7269
  applyPrecision,
@@ -7192,6 +7289,8 @@ export {
7192
7289
  computeWindow,
7193
7290
  connectorsManifest,
7194
7291
  connectorsPanel,
7292
+ connectorsViewManifest,
7293
+ connectorsViewState,
7195
7294
  constraintsOfColumn,
7196
7295
  createChartPanel,
7197
7296
  createConnectorExecutor,