@richardmcquiston01/dashboard-widgets-toolkit 0.14.0 → 0.15.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/core.cjs CHANGED
@@ -688,6 +688,263 @@ function placeAndFillRows(items, columns, spanOf) {
688
688
  return { spans, rows };
689
689
  }
690
690
 
691
+ // src/core/views.ts
692
+ var BASE_VIEW_KEY = "base";
693
+ var MAX_WIDGET_VIEWS = 8;
694
+ var VIEW_CONVERSIONS = {
695
+ tableToBarList: { from: "TABLE", to: "BAR_LIST" },
696
+ tableToGraph: { from: "TABLE", to: "GRAPH" },
697
+ barListToTable: { from: "BAR_LIST", to: "TABLE" },
698
+ graphToTable: { from: "GRAPH", to: "TABLE" },
699
+ barListToGraph: { from: "BAR_LIST", to: "GRAPH" }
700
+ };
701
+ var KIND_LABELS = {
702
+ TEXT: "Text",
703
+ KPI: "Number",
704
+ GAUGE: "Gauge",
705
+ TABLE: "Table",
706
+ BAR_LIST: "Bars",
707
+ ALERT_LIST: "List",
708
+ GRAPH: "Chart"
709
+ };
710
+ function kindLabel(kind) {
711
+ return KIND_LABELS[kind];
712
+ }
713
+ function hasViews(item) {
714
+ return item.views !== void 0 && item.views.length > 0;
715
+ }
716
+ function findView(item, key) {
717
+ return item.views?.find((view) => view.key === key);
718
+ }
719
+ function viewChoices(item) {
720
+ if (!hasViews(item)) return [];
721
+ return [
722
+ {
723
+ key: BASE_VIEW_KEY,
724
+ label: item.baseViewLabel ?? kindLabel(item.kind),
725
+ kind: item.kind
726
+ },
727
+ ...(item.views ?? []).map(({ key, label, kind }) => ({
728
+ key,
729
+ label,
730
+ kind
731
+ }))
732
+ ];
733
+ }
734
+ function isKnownView(item, key) {
735
+ return key !== void 0 && (key === BASE_VIEW_KEY || findView(item, key) !== void 0);
736
+ }
737
+ function effectiveViewKey(item, chosen) {
738
+ if (!hasViews(item)) return BASE_VIEW_KEY;
739
+ if (isKnownView(item, chosen)) return chosen;
740
+ if (isKnownView(item, item.defaultView)) return item.defaultView;
741
+ return BASE_VIEW_KEY;
742
+ }
743
+ function viewKind(item, chosen) {
744
+ return findView(item, effectiveViewKey(item, chosen))?.kind ?? item.kind;
745
+ }
746
+ function cellValue2(cell) {
747
+ const value = cell?.value;
748
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
749
+ }
750
+ function columnName(table, index) {
751
+ return table.columns[index]?.label ?? `#${index + 1}`;
752
+ }
753
+ function checkColumn(table, index, field, context) {
754
+ if (!Number.isInteger(index) || index < 0 || index >= table.columns.length) {
755
+ return `${context.where}: ${field} column ${index} does not exist (the table has ${table.columns.length} columns, numbered from 0).`;
756
+ }
757
+ return void 0;
758
+ }
759
+ function numericColumn(table, index, context) {
760
+ const numbers = [];
761
+ for (const [rowIndex, row] of table.rows.entries()) {
762
+ const value = cellValue2(row[index]);
763
+ if (value === void 0) {
764
+ return err(
765
+ `${context.where}: row ${rowIndex + 1}, column ${index + 1} ("${columnName(table, index)}") has no numeric value. Add value to the cells.`
766
+ );
767
+ }
768
+ numbers.push(value);
769
+ }
770
+ return ok(numbers);
771
+ }
772
+ function tableToBarList(table, conversion, context) {
773
+ const bad = checkColumn(table, conversion.label, "label", context) ?? checkColumn(table, conversion.value, "value", context);
774
+ if (bad !== void 0) return err(bad);
775
+ const numbers = numericColumn(table, conversion.value, context);
776
+ if (!numbers.ok) return numbers;
777
+ const items = table.rows.map((row, index) => ({
778
+ label: row[conversion.label]?.text ?? "",
779
+ value: numbers.value[index],
780
+ display: row[conversion.value]?.text ?? String(numbers.value[index])
781
+ }));
782
+ return ok({ kind: "BAR_LIST", items });
783
+ }
784
+ function tableToGraph(table, conversion, context) {
785
+ if (conversion.values.length === 0 || conversion.values.length > MAX_GRAPH_SERIES) {
786
+ return err(
787
+ `${context.where}: a chart needs 1 to ${MAX_GRAPH_SERIES} series columns, got ${conversion.values.length}.`
788
+ );
789
+ }
790
+ let bad = checkColumn(
791
+ table,
792
+ conversion.label,
793
+ "label",
794
+ context
795
+ );
796
+ for (const index of conversion.values) {
797
+ bad ??= checkColumn(table, index, "series", context);
798
+ }
799
+ if (bad !== void 0) return err(bad);
800
+ const series = [];
801
+ for (const index of conversion.values) {
802
+ const numbers = numericColumn(table, index, context);
803
+ if (!numbers.ok) return numbers;
804
+ series.push({
805
+ name: columnName(table, index),
806
+ points: table.rows.map((row, rowIndex) => ({
807
+ label: row[conversion.label]?.text ?? "",
808
+ value: numbers.value[rowIndex]
809
+ }))
810
+ });
811
+ }
812
+ return ok({
813
+ kind: "GRAPH",
814
+ series,
815
+ chartType: conversion.chartType,
816
+ valueFormat: conversion.valueFormat ?? "number",
817
+ ...conversion.currency === void 0 ? {} : { currency: conversion.currency },
818
+ xLabel: columnName(table, conversion.label)
819
+ });
820
+ }
821
+ function barListToTable(list, conversion) {
822
+ return ok({
823
+ kind: "TABLE",
824
+ columns: [
825
+ { label: conversion.labelHeading ?? "Name" },
826
+ { label: conversion.valueHeading ?? "Value", numeric: true }
827
+ ],
828
+ rows: list.items.map((item) => [
829
+ { text: item.label },
830
+ { text: item.display ?? String(item.value), value: item.value }
831
+ ])
832
+ });
833
+ }
834
+ function graphToTable(graph, context) {
835
+ const first = graph.series[0];
836
+ if (first === void 0)
837
+ return err(`${context.where}: the chart has no series.`);
838
+ const format = {
839
+ ...graph.currency === void 0 ? {} : { currency: graph.currency },
840
+ ...context.locale === void 0 ? {} : { locale: context.locale }
841
+ };
842
+ return ok({
843
+ kind: "TABLE",
844
+ columns: [
845
+ { label: graph.xLabel ?? "Label" },
846
+ ...graph.series.map((series) => ({ label: series.name, numeric: true }))
847
+ ],
848
+ rows: first.points.map((point, index) => [
849
+ { text: point.label },
850
+ ...graph.series.map((series) => {
851
+ const value = series.points[index]?.value;
852
+ return value === void 0 ? { text: "\u2014" } : { text: formatValue(value, graph.valueFormat, format), value };
853
+ })
854
+ ])
855
+ });
856
+ }
857
+ function barListToGraph(list, conversion) {
858
+ return ok({
859
+ kind: "GRAPH",
860
+ series: [
861
+ {
862
+ name: conversion.seriesName ?? "Value",
863
+ points: list.items.map((item) => ({
864
+ label: item.label,
865
+ value: item.value
866
+ }))
867
+ }
868
+ ],
869
+ chartType: conversion.chartType,
870
+ valueFormat: conversion.valueFormat ?? "number",
871
+ ...conversion.currency === void 0 ? {} : { currency: conversion.currency }
872
+ });
873
+ }
874
+ function convertView(widgetKey, view, data, options = {}) {
875
+ const conversion = view.convert;
876
+ const context = {
877
+ where: `Widget ${JSON.stringify(widgetKey)} view ${JSON.stringify(view.key)}`,
878
+ ...options.locale === void 0 ? {} : { locale: options.locale }
879
+ };
880
+ const expected = VIEW_CONVERSIONS[conversion.type]?.from;
881
+ if (expected === void 0) {
882
+ return err(
883
+ `${context.where}: unknown conversion type ${JSON.stringify(conversion.type)}.`
884
+ );
885
+ }
886
+ if (data.kind !== expected) {
887
+ return err(
888
+ `${context.where}: ${conversion.type} reads a ${expected} payload, but the widget returned ${data.kind}.`
889
+ );
890
+ }
891
+ switch (conversion.type) {
892
+ case "tableToBarList":
893
+ return tableToBarList(data, conversion, context);
894
+ case "tableToGraph":
895
+ return tableToGraph(data, conversion, context);
896
+ case "barListToTable":
897
+ return barListToTable(data, conversion);
898
+ case "graphToTable":
899
+ return graphToTable(data, context);
900
+ case "barListToGraph":
901
+ return barListToGraph(data, conversion);
902
+ }
903
+ }
904
+ function viewNote(view, data) {
905
+ if (data?.kind !== "TABLE") return "";
906
+ const conversion = view.convert;
907
+ let indexes;
908
+ if (conversion.type === "tableToBarList") {
909
+ indexes = [conversion.label, conversion.value];
910
+ } else if (conversion.type === "tableToGraph") {
911
+ indexes = [conversion.label, ...conversion.values];
912
+ } else {
913
+ return "";
914
+ }
915
+ const names = indexes.map(
916
+ (index) => data.columns[index]?.label ?? `#${index + 1}`
917
+ );
918
+ return `Shows ${names.join(", ")} only.`;
919
+ }
920
+ function applyView(widget, chosen, options = {}) {
921
+ const key = effectiveViewKey(widget.definition, chosen);
922
+ const view = findView(widget.definition, key);
923
+ if (view === void 0) return widget;
924
+ const definition = {
925
+ ...widget.definition,
926
+ kind: view.kind
927
+ };
928
+ if (widget.status === "loading") return { ...widget, definition };
929
+ if (widget.status === "empty") return { ...widget, definition };
930
+ if (widget.status === "error") return { ...widget, definition };
931
+ const converted = convertView(
932
+ widget.definition.key,
933
+ view,
934
+ widget.data,
935
+ options
936
+ );
937
+ if (!converted.ok) {
938
+ return {
939
+ definition,
940
+ status: "error",
941
+ error: converted.error,
942
+ ...widget.options === void 0 ? {} : { options: widget.options }
943
+ };
944
+ }
945
+ return { ...widget, definition, data: converted.value };
946
+ }
947
+
691
948
  // src/core/options.ts
692
949
  var DATE_RANGE_PRESETS = [
693
950
  "today",
@@ -993,6 +1250,7 @@ function parseOne(raw) {
993
1250
  const width = raw["width"];
994
1251
  const flexible = raw["flexible"];
995
1252
  const options = raw["options"];
1253
+ const view = raw["view"];
996
1254
  const cleanTitle = typeof title === "string" ? title.trim().slice(0, MAX_WIDGET_TITLE_LENGTH) : "";
997
1255
  const chosen = {};
998
1256
  if (isRecord(options)) {
@@ -1005,7 +1263,8 @@ function parseOne(raw) {
1005
1263
  ...cleanTitle === "" ? {} : { title: cleanTitle },
1006
1264
  ...isWidgetWidth(width) ? { width } : {},
1007
1265
  ...typeof flexible === "boolean" ? { flexible } : {},
1008
- ...Object.keys(chosen).length === 0 ? {} : { options: chosen }
1266
+ ...Object.keys(chosen).length === 0 ? {} : { options: chosen },
1267
+ ...typeof view === "string" && view !== "" && view.length <= 80 ? { view } : {}
1009
1268
  };
1010
1269
  return Object.keys(settings).length === 0 ? void 0 : settings;
1011
1270
  }
@@ -1032,7 +1291,8 @@ function serializeSettings(settings) {
1032
1291
  ...one.title === void 0 ? {} : { title: one.title },
1033
1292
  ...one.width === void 0 ? {} : { width: one.width },
1034
1293
  ...one.flexible === void 0 ? {} : { flexible: one.flexible },
1035
- ...one.options === void 0 || Object.keys(one.options).length === 0 ? {} : { options: { ...one.options } }
1294
+ ...one.options === void 0 || Object.keys(one.options).length === 0 ? {} : { options: { ...one.options } },
1295
+ ...one.view === void 0 ? {} : { view: one.view }
1036
1296
  };
1037
1297
  if (Object.keys(piece).length > 0) out[key] = piece;
1038
1298
  }
@@ -1124,12 +1384,18 @@ function optionValuesFromLayout(definitions, layout, options = {}) {
1124
1384
  }
1125
1385
  function sameSettings(a, b) {
1126
1386
  if (a === b) return true;
1127
- return a?.title === b?.title && a?.width === b?.width && a?.flexible === b?.flexible && sameOptionValues(a?.options ?? {}, b?.options ?? {});
1387
+ return a?.title === b?.title && a?.width === b?.width && a?.flexible === b?.flexible && a?.view === b?.view && sameOptionValues(a?.options ?? {}, b?.options ?? {});
1128
1388
  }
1129
1389
  function setWidgetSettings(layout, key, patch) {
1130
1390
  const before = layout.settings?.[key];
1131
1391
  const draft = { ...before };
1132
- for (const field of ["title", "width", "flexible", "options"]) {
1392
+ for (const field of [
1393
+ "title",
1394
+ "width",
1395
+ "flexible",
1396
+ "options",
1397
+ "view"
1398
+ ]) {
1133
1399
  if (!(field in patch)) continue;
1134
1400
  const value = patch[field];
1135
1401
  if (value === void 0) {
@@ -1155,7 +1421,8 @@ function clearWidgetSettings(layout, key) {
1155
1421
  title: void 0,
1156
1422
  width: void 0,
1157
1423
  flexible: void 0,
1158
- options: void 0
1424
+ options: void 0,
1425
+ view: void 0
1159
1426
  });
1160
1427
  }
1161
1428
  function normalizeTitle(title) {
@@ -1215,7 +1482,8 @@ function normalizeSettings(definitions, layout, options = {}) {
1215
1482
  ...title === void 0 ? {} : { title },
1216
1483
  ...one.width === void 0 ? {} : { width: Math.min(range.max, Math.max(range.min, one.width)) },
1217
1484
  ...one.flexible === void 0 ? {} : { flexible: one.flexible },
1218
- ...Object.keys(chosen).length === 0 ? {} : { options: chosen }
1485
+ ...Object.keys(chosen).length === 0 ? {} : { options: chosen },
1486
+ ...one.view !== void 0 && (one.view === BASE_VIEW_KEY || findView(definition, one.view) !== void 0) ? { view: one.view } : {}
1219
1487
  };
1220
1488
  if (Object.keys(next).length > 0) {
1221
1489
  cleaned[definition.key] = sameSettings(one, next) ? one : next;
@@ -2088,6 +2356,137 @@ function checkOptions(options, kind, problems) {
2088
2356
  );
2089
2357
  });
2090
2358
  }
2359
+ var MAX_VIEW_COLUMN = 1e3;
2360
+ function checkColumnIndex(value, path, problems) {
2361
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 0 || value > MAX_VIEW_COLUMN) {
2362
+ problems.push(
2363
+ `${path} must be a column index (a whole number from 0), got ${typeof value === "number" ? String(value) : describeType2(value)}.`
2364
+ );
2365
+ }
2366
+ }
2367
+ function checkConversion(conversion, path, baseKind, viewKind2, problems) {
2368
+ if (!isRecord2(conversion)) {
2369
+ problems.push(
2370
+ `${path} must be an object with a type, got ${describeType2(conversion)}.`
2371
+ );
2372
+ return;
2373
+ }
2374
+ const type = conversion["type"];
2375
+ const known = typeof type === "string" && Object.hasOwn(VIEW_CONVERSIONS, type) ? VIEW_CONVERSIONS[type] : void 0;
2376
+ if (known === void 0) {
2377
+ problems.push(
2378
+ `${path}.type must be one of ${Object.keys(VIEW_CONVERSIONS).map((name) => `"${name}"`).join(", ")}, got ${describeType2(type)}.`
2379
+ );
2380
+ return;
2381
+ }
2382
+ if (baseKind !== known.from) {
2383
+ problems.push(
2384
+ `${path}.type "${String(type)}" reads a ${known.from} widget, but this one is ${String(baseKind)}.`
2385
+ );
2386
+ }
2387
+ if (viewKind2 !== known.to) {
2388
+ problems.push(
2389
+ `${path}.type "${String(type)}" produces ${known.to}, but the view's kind is ${String(viewKind2)}.`
2390
+ );
2391
+ }
2392
+ switch (type) {
2393
+ case "tableToBarList":
2394
+ checkColumnIndex(conversion["label"], `${path}.label`, problems);
2395
+ checkColumnIndex(conversion["value"], `${path}.value`, problems);
2396
+ break;
2397
+ case "tableToGraph": {
2398
+ checkColumnIndex(conversion["label"], `${path}.label`, problems);
2399
+ const values = conversion["values"];
2400
+ if (!Array.isArray(values) || values.length === 0) {
2401
+ problems.push(`${path}.values must list 1 or more column indexes.`);
2402
+ } else if (values.length > MAX_GRAPH_SERIES) {
2403
+ problems.push(
2404
+ `${path}.values lists ${values.length} series; a chart carries at most ${MAX_GRAPH_SERIES}.`
2405
+ );
2406
+ } else {
2407
+ values.forEach(
2408
+ (index, at) => checkColumnIndex(index, `${path}.values[${at}]`, problems)
2409
+ );
2410
+ }
2411
+ if (conversion["chartType"] !== "bar" && conversion["chartType"] !== "line") {
2412
+ problems.push(`${path}.chartType must be "bar" or "line".`);
2413
+ }
2414
+ break;
2415
+ }
2416
+ case "barListToGraph":
2417
+ if (conversion["chartType"] !== "bar" && conversion["chartType"] !== "line") {
2418
+ problems.push(`${path}.chartType must be "bar" or "line".`);
2419
+ }
2420
+ break;
2421
+ }
2422
+ if (conversion["valueFormat"] !== void 0 && !VALUE_FORMATS.includes(conversion["valueFormat"])) {
2423
+ problems.push(
2424
+ `${path}.valueFormat must be one of ${VALUE_FORMATS.map((f) => `"${f}"`).join(", ")}.`
2425
+ );
2426
+ }
2427
+ }
2428
+ function checkViews(value, problems) {
2429
+ const views = value["views"];
2430
+ const defaultView = value["defaultView"];
2431
+ optionalString(value, "baseViewLabel", "", problems);
2432
+ if (value["baseViewLabel"] === "") {
2433
+ problems.push("baseViewLabel must not be empty.");
2434
+ }
2435
+ const declared = /* @__PURE__ */ new Set([BASE_VIEW_KEY]);
2436
+ if (views !== void 0) {
2437
+ if (!Array.isArray(views)) {
2438
+ problems.push(`views must be an array, got ${describeType2(views)}.`);
2439
+ } else if (views.length > MAX_WIDGET_VIEWS) {
2440
+ problems.push(
2441
+ `views lists ${views.length} views; the most a widget may declare is ${MAX_WIDGET_VIEWS}.`
2442
+ );
2443
+ } else {
2444
+ views.forEach((view, index) => {
2445
+ const path = `views[${index}]`;
2446
+ if (!isRecord2(view)) {
2447
+ problems.push(
2448
+ `${path} must be an object, got ${describeType2(view)}.`
2449
+ );
2450
+ return;
2451
+ }
2452
+ const key = view["key"];
2453
+ if (typeof key !== "string" || key.trim() === "") {
2454
+ problems.push(`${path}.key must be a non-empty string.`);
2455
+ } else if (declared.has(key)) {
2456
+ problems.push(
2457
+ key === BASE_VIEW_KEY ? `${path}.key "${BASE_VIEW_KEY}" is reserved for the widget's own kind.` : `${path}.key "${key}" is used twice.`
2458
+ );
2459
+ } else {
2460
+ declared.add(key);
2461
+ }
2462
+ if (typeof view["label"] !== "string" || view["label"].trim() === "") {
2463
+ problems.push(`${path}.label must be a non-empty string.`);
2464
+ }
2465
+ requireOneOf(view, "kind", WIDGET_KINDS, path, problems);
2466
+ if (view["convert"] === void 0) {
2467
+ problems.push(
2468
+ `${path}.convert is required: views supplied by a provider are not supported yet.`
2469
+ );
2470
+ } else {
2471
+ checkConversion(
2472
+ view["convert"],
2473
+ `${path}.convert`,
2474
+ value["kind"],
2475
+ view["kind"],
2476
+ problems
2477
+ );
2478
+ }
2479
+ });
2480
+ }
2481
+ }
2482
+ if (defaultView !== void 0) {
2483
+ if (typeof defaultView !== "string" || !declared.has(defaultView)) {
2484
+ problems.push(
2485
+ `defaultView must be "${BASE_VIEW_KEY}" or the key of a declared view, got ${typeof defaultView === "string" ? JSON.stringify(defaultView) : describeType2(defaultView)}.`
2486
+ );
2487
+ }
2488
+ }
2489
+ }
2091
2490
  function formatProblems(prefix, problems) {
2092
2491
  const shown = problems.slice(0, MAX_REPORTED_PROBLEMS);
2093
2492
  const more = problems.length - shown.length;
@@ -2164,6 +2563,7 @@ function validateWidgetDefinition(value) {
2164
2563
  checkTableControlsOption(value["tableControls"], value["kind"], problems);
2165
2564
  checkLockedOption(value["locked"], problems);
2166
2565
  checkOptions(value["options"], value["kind"], problems);
2566
+ checkViews(value, problems);
2167
2567
  if (value["page"] !== void 0) {
2168
2568
  if (typeof value["page"] !== "string" || value["page"].trim() === "") {
2169
2569
  problems.push(
@@ -3798,6 +4198,7 @@ function indent(block) {
3798
4198
  return block.split("\n").map((line) => ` ${line}`).join("\n");
3799
4199
  }
3800
4200
 
4201
+ exports.BASE_VIEW_KEY = BASE_VIEW_KEY;
3801
4202
  exports.DATE_RANGE_PRESETS = DATE_RANGE_PRESETS;
3802
4203
  exports.DEFAULT_COMPARISON_LABEL = DEFAULT_COMPARISON_LABEL;
3803
4204
  exports.DEFAULT_CURRENCY = DEFAULT_CURRENCY;
@@ -3819,11 +4220,13 @@ exports.MAX_REPORTED_PROBLEMS = MAX_REPORTED_PROBLEMS;
3819
4220
  exports.MAX_TEXT_OPTION_LENGTH = MAX_TEXT_OPTION_LENGTH;
3820
4221
  exports.MAX_WIDGET_OPTIONS = MAX_WIDGET_OPTIONS;
3821
4222
  exports.MAX_WIDGET_TITLE_LENGTH = MAX_WIDGET_TITLE_LENGTH;
4223
+ exports.MAX_WIDGET_VIEWS = MAX_WIDGET_VIEWS;
3822
4224
  exports.MAX_WIDGET_WIDTH = MAX_WIDGET_WIDTH;
3823
4225
  exports.MIN_WIDGET_WIDTH = MIN_WIDGET_WIDTH;
3824
4226
  exports.OPTION_KEY_PATTERN = OPTION_KEY_PATTERN;
3825
4227
  exports.THEME_TOKEN_VARIABLES = THEME_TOKEN_VARIABLES;
3826
4228
  exports.VALUE_FORMATS = VALUE_FORMATS;
4229
+ exports.VIEW_CONVERSIONS = VIEW_CONVERSIONS;
3827
4230
  exports.WIDGET_FILLS = WIDGET_FILLS;
3828
4231
  exports.WIDGET_KINDS = WIDGET_KINDS;
3829
4232
  exports.WIDGET_OPTION_TYPES = WIDGET_OPTION_TYPES;
@@ -3832,11 +4235,13 @@ exports.WIDTH_COLUMNS = WIDTH_COLUMNS;
3832
4235
  exports.addPage = addPage;
3833
4236
  exports.applyClientOptions = applyClientOptions;
3834
4237
  exports.applySettings = applySettings;
4238
+ exports.applyView = applyView;
3835
4239
  exports.assignPages = assignPages;
3836
4240
  exports.baseColumnSpan = baseColumnSpan;
3837
4241
  exports.cacheKeyFor = cacheKeyFor;
3838
4242
  exports.clearWidgetSettings = clearWidgetSettings;
3839
4243
  exports.coerceOptionValue = coerceOptionValue;
4244
+ exports.convertView = convertView;
3840
4245
  exports.createLayoutPersistence = createLayoutPersistence;
3841
4246
  exports.createTheme = createTheme;
3842
4247
  exports.createWidgetLoader = createWidgetLoader;
@@ -3846,6 +4251,7 @@ exports.defineWidget = defineWidget;
3846
4251
  exports.deriveDetailData = deriveDetailData;
3847
4252
  exports.describeUnknownError = describeUnknownError;
3848
4253
  exports.effectiveDefinitions = effectiveDefinitions;
4254
+ exports.effectiveViewKey = effectiveViewKey;
3849
4255
  exports.emptyTextFor = emptyTextFor;
3850
4256
  exports.emptyWidget = emptyWidget;
3851
4257
  exports.enforceLocks = enforceLocks;
@@ -3856,12 +4262,14 @@ exports.fillWidthSpans = fillWidthSpans;
3856
4262
  exports.fillsHeight = fillsHeight;
3857
4263
  exports.fillsWidth = fillsWidth;
3858
4264
  exports.finalizeWidget = finalizeWidget;
4265
+ exports.findView = findView;
3859
4266
  exports.fitCount = fitCount;
3860
4267
  exports.formatCount = formatCount;
3861
4268
  exports.formatPercentChange = formatPercentChange;
3862
4269
  exports.formatValue = formatValue;
3863
4270
  exports.fromLegacyDefinition = fromLegacyDefinition;
3864
4271
  exports.hasPages = hasPages;
4272
+ exports.hasViews = hasViews;
3865
4273
  exports.hiddenWidgets = hiddenWidgets;
3866
4274
  exports.hideWidget = hideWidget;
3867
4275
  exports.isClientApplied = isClientApplied;
@@ -3879,6 +4287,7 @@ exports.isWidgetKind = isWidgetKind;
3879
4287
  exports.isWidgetVisibleTo = isWidgetVisibleTo;
3880
4288
  exports.isWidgetWidth = isWidgetWidth;
3881
4289
  exports.itemWidth = itemWidth;
4290
+ exports.kindLabel = kindLabel;
3882
4291
  exports.kpiDelta = kpiDelta;
3883
4292
  exports.labelStride = labelStride;
3884
4293
  exports.loadingWidgets = loadingWidgets;
@@ -3945,6 +4354,9 @@ exports.utf8Length = utf8Length;
3945
4354
  exports.validateDetailData = validateDetailData;
3946
4355
  exports.validateWidgetData = validateWidgetData;
3947
4356
  exports.validateWidgetDefinition = validateWidgetDefinition;
4357
+ exports.viewChoices = viewChoices;
4358
+ exports.viewKind = viewKind;
4359
+ exports.viewNote = viewNote;
3948
4360
  exports.visibleWidgets = visibleWidgets;
3949
4361
  exports.widgetOptionValues = widgetOptionValues;
3950
4362
  exports.widgetsFor = widgetsFor;