@devicechain/dashboards 0.24.0-rc.1 → 0.25.0-rc.2
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 +5 -1
- package/dist/hub.d.ts +3 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +137 -6
- package/dist/index.js.map +2 -2
- package/dist/recorded.d.ts +1 -0
- package/dist/time-range.d.ts +40 -0
- package/dist/types.d.ts +2 -1
- package/dist/widget-descriptor.d.ts +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -124,7 +124,11 @@ overlap, so there is no stacking order to manage.
|
|
|
124
124
|
|
|
125
125
|
A board has a time range: `TIME_RANGE_PRESETS` (15 minutes to 7 days),
|
|
126
126
|
`initialTimeRange`, `pauseRange` / `resumeRange` and `rangeWindow` manage it, and
|
|
127
|
-
`
|
|
127
|
+
`timeRangeLinkFromSearch` reads the `range`, `paused` and `from` / `to` URL parameters
|
|
128
|
+
(`timeRangeFromSearch` reads only `range` and `paused`, for a host that knows no fixed window). A fixed
|
|
129
|
+
from-to window is an additive variant of the same state: `absoluteRange` builds it and
|
|
130
|
+
`TimeRangeState.absolute` marks it, while `paused`, `pausedAt` and `spanSeconds` still describe the
|
|
131
|
+
window as a frozen rolling range, so code that only knows rolling ranges keeps working. Its density
|
|
128
132
|
(`CANVAS_DENSITIES`: `compact`, `comfortable`, `wall`) scales every text and
|
|
129
133
|
spacing size by `DENSITY_SCALE`; a host may override the board's own value at
|
|
130
134
|
view time.
|
package/dist/hub.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface DeviceResolver {
|
|
|
12
12
|
total: number;
|
|
13
13
|
}>;
|
|
14
14
|
declaredMetrics?(deviceType: string): Promise<string[] | null>;
|
|
15
|
+
deviceType?(deviceToken: string): Promise<string | null>;
|
|
15
16
|
}
|
|
16
17
|
export interface WidgetStreamSink {
|
|
17
18
|
next: (sample: MeasurementSample) => void;
|
|
@@ -98,6 +99,7 @@ export interface WidgetDataSource {
|
|
|
98
99
|
subscribeMembers?(datasource: DatasourceSelector, sink: MemberSink): () => void;
|
|
99
100
|
readMemberSeeds?(deviceTokens: readonly string[], plan: MemberSeedPlan, onSeed: (deviceToken: string, seed: MemberSeed | null, failure?: SeedFailure) => void, cancelled?: () => boolean): Promise<void>;
|
|
100
101
|
declaredMetrics?(deviceType: string): Promise<readonly string[] | null>;
|
|
102
|
+
declaredMetricsForDevice?(deviceToken: string): Promise<readonly string[] | null>;
|
|
101
103
|
subscribePresence?(datasource: DatasourceSelector, sink: PresenceSink): () => void;
|
|
102
104
|
}
|
|
103
105
|
export declare class DashboardHub implements WidgetDataSource, WidgetActions {
|
|
@@ -120,6 +122,7 @@ export declare class DashboardHub implements WidgetDataSource, WidgetActions {
|
|
|
120
122
|
private resolveRoster;
|
|
121
123
|
private readonly declared;
|
|
122
124
|
declaredMetrics(deviceType: string): Promise<readonly string[] | null>;
|
|
125
|
+
declaredMetricsForDevice(deviceToken: string): Promise<readonly string[] | null>;
|
|
123
126
|
private readonly seedLimiter;
|
|
124
127
|
private readonly seedReads;
|
|
125
128
|
readMemberSeeds(deviceTokens: readonly string[], plan: MemberSeedPlan, onSeed: (deviceToken: string, seed: MemberSeed | null, failure?: SeedFailure) => void, cancelled?: () => boolean): Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,7 @@ export type { MeasurementBucket } from './queries';
|
|
|
23
23
|
export { ANCHOR_PAGE_SIZE } from './resolver';
|
|
24
24
|
export type { MemberBucketCriteria, MemberBucketRead, MemberRef, MemberRoster, MemberSeed, MemberSeedPlan, MemberSink, PresenceSink, SeedFailure, } from './members';
|
|
25
25
|
export { defaultHistoryWindow, fetchWidgetHistory, historyWindowFor, type HistoryWindow } from './history';
|
|
26
|
-
export { DEFAULT_TIME_RANGE_SECONDS, MAX_SEED_BUCKETS, MAX_TIME_RANGE_SECONDS, MIN_TIME_RANGE_SECONDS, TIME_RANGE_PRESETS, bucketSecondsFor, initialTimeRange, isValidSpanSeconds, parsePausedParam, parseRangeParam, pauseRange, presetIdOf, rangeEnd, rangeWindow, resumeRange, seedBucketCount, setBoardTimeRange, spanLabel, timeRangeFromSearch, withSpan, type RangeWindow, type TimeRangePresetId, type TimeRangeState, } from './time-range';
|
|
26
|
+
export { ABSOLUTE_FUTURE_SKEW_MS, DEFAULT_TIME_RANGE_SECONDS, EARLIEST_ABSOLUTE_MS, MAX_ABSOLUTE_SPAN_SECONDS, MIN_ABSOLUTE_SPAN_SECONDS, MAX_SEED_BUCKETS, MAX_TIME_RANGE_SECONDS, MIN_TIME_RANGE_SECONDS, TIME_RANGE_PRESETS, absoluteRange, absoluteRangeProblem, absoluteToParams, bucketSecondsFor, isAbsolute, leaveAbsolute, parseAbsoluteParams, parseInstantParam, initialTimeRange, isValidSpanSeconds, parsePausedParam, parseRangeParam, pauseRange, presetIdOf, rangeEnd, rangeWindow, resumeRange, seedBucketCount, setBoardTimeRange, spanLabel, timeRangeFromSearch, timeRangeLinkFromSearch, withSpan, type AbsoluteLinkRejection, type AbsoluteRange, type AbsoluteRangeProblem, type RangeWindow, type TimeRangeLink, type TimeRangePresetId, type TimeRangeState, } from './time-range';
|
|
27
27
|
export type { AggregateResult, AggregateSpan, AggregateTrendPoint, AggregateStreamState, AlarmStreamState, AlarmTypeTab, AlarmTypeTabs, CommandStreamState, FleetMember, FleetState, MemberPresence, LocationStreamState, MeasurementAggregate, MeasurementStreamState, } from './channel-snapshots';
|
|
28
28
|
export { applyOptionPatch, clampNumberOption, enumValues, numberSpec, validateOptions, HOST_OPTION_CONTROLS, type HostOptionControl, type BooleanOptionSpec, type DefaultsOf, type EnumOptionSpec, type ListItemFieldSpec, type ListOptionSpec, type GreaterThanConstraint, type NumberOptionSpec, type OptionConstraint, type OptionIssue, type OptionIssueCode, type OptionKeysOfKind, type OptionSpec, type OptionsOf, type RequiredOptionKeys, type SpecValue, type StringOptionSpec, type ValidateOptionsContext, type WidgetOptionSpecs, } from './option-schema';
|
|
29
29
|
export { SDK_API_VERSION, defineWidgetDescriptor, isBuiltinWidgetId, isNamespacedWidgetId, type AckOptionRef, type BuiltinWidgetId, type ChannelBindingPolicy, type ChannelSnapshot, type ConstBinding, type DatasourcePolicy, type DatasourcePolicyFor, type DatasourceSelectorKind, type InteractionsFor, type NamespacedWidgetId, type NumberOptionRef, type StringOptionRef, type WidgetChannel, type WidgetDescriptor, type WidgetDisplay, type WidgetId, type WidgetInteractionDeclaration, FALLBACK_DEFAULT_SPAN, pinnedAxes, type WidgetLayoutSpec, type WidgetResizeMode, type WidgetSpan, } from './widget-descriptor';
|
package/dist/index.js
CHANGED
|
@@ -76,7 +76,8 @@ var WIDGET_TYPES = [
|
|
|
76
76
|
"fleet-table",
|
|
77
77
|
"fleet-count",
|
|
78
78
|
"device-status",
|
|
79
|
-
"online-doughnut"
|
|
79
|
+
"online-doughnut",
|
|
80
|
+
"history-table"
|
|
80
81
|
];
|
|
81
82
|
var PLACEMENT_ANCHORS = [
|
|
82
83
|
"top-left",
|
|
@@ -536,7 +537,41 @@ var MAX_TIME_RANGE_SECONDS = 7 * 24 * 60 * 60;
|
|
|
536
537
|
function isValidSpanSeconds(v) {
|
|
537
538
|
return typeof v === "number" && Number.isInteger(v) && v >= MIN_TIME_RANGE_SECONDS && v <= MAX_TIME_RANGE_SECONDS;
|
|
538
539
|
}
|
|
540
|
+
var MIN_ABSOLUTE_SPAN_SECONDS = 60;
|
|
541
|
+
var MAX_ABSOLUTE_SPAN_SECONDS = 31 * 24 * 60 * 60;
|
|
542
|
+
var EARLIEST_ABSOLUTE_MS = Date.UTC(2e3, 0, 1);
|
|
543
|
+
var ABSOLUTE_FUTURE_SKEW_MS = 60 * 1e3;
|
|
544
|
+
function absoluteRangeProblem(fromMs, toMs, now) {
|
|
545
|
+
if (!Number.isFinite(fromMs) || !Number.isFinite(toMs)) return "unparseable";
|
|
546
|
+
if (fromMs >= toMs) return "order";
|
|
547
|
+
if (fromMs < EARLIEST_ABSOLUTE_MS) return "tooEarly";
|
|
548
|
+
if (toMs > now + ABSOLUTE_FUTURE_SKEW_MS) return "future";
|
|
549
|
+
const seconds = (Math.floor(toMs / 1e3) * 1e3 - Math.floor(fromMs / 1e3) * 1e3) / 1e3;
|
|
550
|
+
if (seconds < MIN_ABSOLUTE_SPAN_SECONDS) return "tooShort";
|
|
551
|
+
if (seconds > MAX_ABSOLUTE_SPAN_SECONDS) return "tooLong";
|
|
552
|
+
return void 0;
|
|
553
|
+
}
|
|
554
|
+
function isAbsolute(state) {
|
|
555
|
+
return state.absolute !== void 0;
|
|
556
|
+
}
|
|
557
|
+
function absoluteRange(fromMs, toMs, now = Date.now()) {
|
|
558
|
+
const problem = absoluteRangeProblem(fromMs, toMs, now);
|
|
559
|
+
if (problem) return { problem };
|
|
560
|
+
const from = Math.floor(fromMs / 1e3) * 1e3;
|
|
561
|
+
const to = Math.floor(toMs / 1e3) * 1e3;
|
|
562
|
+
return {
|
|
563
|
+
state: { spanSeconds: (to - from) / 1e3, paused: true, pausedAt: to, absolute: { fromMs: from, toMs: to } }
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
function leaveAbsolute(state) {
|
|
567
|
+
if (!state.absolute) return state;
|
|
568
|
+
return { spanSeconds: Math.min(state.spanSeconds, MAX_TIME_RANGE_SECONDS), paused: false };
|
|
569
|
+
}
|
|
539
570
|
function initialTimeRange(defaultSeconds, link = {}, now = Date.now()) {
|
|
571
|
+
if (link.absolute) {
|
|
572
|
+
const made = absoluteRange(link.absolute.fromMs, link.absolute.toMs, now);
|
|
573
|
+
if ("state" in made) return made.state;
|
|
574
|
+
}
|
|
540
575
|
const spanSeconds = link.spanSeconds ?? (isValidSpanSeconds(defaultSeconds) ? defaultSeconds : DEFAULT_TIME_RANGE_SECONDS);
|
|
541
576
|
return link.paused ? { spanSeconds, paused: true, pausedAt: now } : { spanSeconds, paused: false };
|
|
542
577
|
}
|
|
@@ -544,9 +579,11 @@ function pauseRange(state, now) {
|
|
|
544
579
|
return state.paused ? state : { spanSeconds: state.spanSeconds, paused: true, pausedAt: now };
|
|
545
580
|
}
|
|
546
581
|
function resumeRange(state) {
|
|
582
|
+
if (state.absolute) return leaveAbsolute(state);
|
|
547
583
|
return state.paused ? { spanSeconds: state.spanSeconds, paused: false } : state;
|
|
548
584
|
}
|
|
549
585
|
function withSpan(state, spanSeconds) {
|
|
586
|
+
if (state.absolute) return state;
|
|
550
587
|
return isValidSpanSeconds(spanSeconds) ? { ...state, spanSeconds } : state;
|
|
551
588
|
}
|
|
552
589
|
function rangeEnd(state, now) {
|
|
@@ -575,6 +612,26 @@ function parseRangeParam(value) {
|
|
|
575
612
|
function parsePausedParam(value) {
|
|
576
613
|
return value === "1";
|
|
577
614
|
}
|
|
615
|
+
var RFC3339_WITH_ZONE = /^\d{4}-\d{2}-\d{2}[Tt]\d{2}:\d{2}(:\d{2}(\.\d{1,9})?)?([Zz]|[+-]\d{2}:\d{2})$/;
|
|
616
|
+
function parseInstantParam(value) {
|
|
617
|
+
if (!value || !RFC3339_WITH_ZONE.test(value)) return void 0;
|
|
618
|
+
const ms = Date.parse(value);
|
|
619
|
+
return Number.isNaN(ms) ? void 0 : ms;
|
|
620
|
+
}
|
|
621
|
+
function parseAbsoluteParams(from, to, now = Date.now()) {
|
|
622
|
+
if (from == null && to == null) return {};
|
|
623
|
+
const raw = { from: from ?? "", to: to ?? "" };
|
|
624
|
+
if (!from || !to) return { rejected: { reason: "incomplete", ...raw } };
|
|
625
|
+
const fromMs = parseInstantParam(from);
|
|
626
|
+
const toMs = parseInstantParam(to);
|
|
627
|
+
if (fromMs === void 0 || toMs === void 0) return { rejected: { reason: "unparseable", ...raw } };
|
|
628
|
+
const made = absoluteRange(fromMs, toMs, now);
|
|
629
|
+
if ("problem" in made) return { rejected: { reason: made.problem, ...raw } };
|
|
630
|
+
return { absolute: made.state.absolute };
|
|
631
|
+
}
|
|
632
|
+
function absoluteToParams(a) {
|
|
633
|
+
return { from: new Date(a.fromMs).toISOString(), to: new Date(a.toMs).toISOString() };
|
|
634
|
+
}
|
|
578
635
|
function timeRangeFromSearch(search) {
|
|
579
636
|
let params;
|
|
580
637
|
try {
|
|
@@ -588,6 +645,19 @@ function timeRangeFromSearch(search) {
|
|
|
588
645
|
if (parsePausedParam(params.get("paused"))) link.paused = true;
|
|
589
646
|
return link;
|
|
590
647
|
}
|
|
648
|
+
function timeRangeLinkFromSearch(search, now = Date.now()) {
|
|
649
|
+
let params;
|
|
650
|
+
try {
|
|
651
|
+
params = new URLSearchParams(search);
|
|
652
|
+
} catch {
|
|
653
|
+
return {};
|
|
654
|
+
}
|
|
655
|
+
const abs = parseAbsoluteParams(params.get("from"), params.get("to"), now);
|
|
656
|
+
if (abs.absolute) return { absolute: abs.absolute };
|
|
657
|
+
const link = timeRangeFromSearch(search);
|
|
658
|
+
if (abs.rejected) link.rejected = abs.rejected;
|
|
659
|
+
return link;
|
|
660
|
+
}
|
|
591
661
|
function presetIdOf(spanSeconds) {
|
|
592
662
|
return TIME_RANGE_PRESETS.find((p) => p.seconds === spanSeconds)?.id;
|
|
593
663
|
}
|
|
@@ -2309,6 +2379,16 @@ var DashboardHub = class {
|
|
|
2309
2379
|
}
|
|
2310
2380
|
return pending;
|
|
2311
2381
|
}
|
|
2382
|
+
async declaredMetricsForDevice(deviceToken) {
|
|
2383
|
+
const typeOf = this.resolver.deviceType;
|
|
2384
|
+
if (!typeOf) return null;
|
|
2385
|
+
try {
|
|
2386
|
+
const type = await typeOf.call(this.resolver, deviceToken);
|
|
2387
|
+
return type ? await this.declaredMetrics(type) : null;
|
|
2388
|
+
} catch {
|
|
2389
|
+
return null;
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2312
2392
|
async readMemberSeeds(deviceTokens, plan, onSeed, cancelled = () => false) {
|
|
2313
2393
|
await Promise.all(
|
|
2314
2394
|
deviceTokens.map(async (token) => {
|
|
@@ -2971,6 +3051,7 @@ var DashboardHub = class {
|
|
|
2971
3051
|
// src/synthetic.ts
|
|
2972
3052
|
var SYNTHETIC_GENERATORS = ["sine", "ramp", "random-walk"];
|
|
2973
3053
|
var DEFAULT_NAME = "value";
|
|
3054
|
+
var MAX_PREVIEW_BUCKETS = 500;
|
|
2974
3055
|
var SYNTHETIC_DEVICE_TYPES = {
|
|
2975
3056
|
"thermostat-01": { token: "thermostat", name: "Thermostat" },
|
|
2976
3057
|
"sensor-14": { token: "sensor", name: "Sensor" },
|
|
@@ -3232,6 +3313,22 @@ var SyntheticDataSource = class {
|
|
|
3232
3313
|
const names = datasource.measurements.length > 0 ? datasource.measurements : [DEFAULT_NAME];
|
|
3233
3314
|
const from = Date.parse(window2.startTime);
|
|
3234
3315
|
const to = Date.parse(window2.endTime);
|
|
3316
|
+
const width = window2.intervalSeconds * 1e3;
|
|
3317
|
+
if (width > 0 && width < to - from) {
|
|
3318
|
+
const aligned = Math.floor(from / width) * width;
|
|
3319
|
+
const total = Math.ceil((to - aligned) / width);
|
|
3320
|
+
const count = Math.min(total, MAX_PREVIEW_BUCKETS);
|
|
3321
|
+
const first = aligned + (total - count) * width;
|
|
3322
|
+
return names.flatMap((name) => {
|
|
3323
|
+
const walk = /* @__PURE__ */ new Map();
|
|
3324
|
+
return Array.from({ length: count }, (_, i) => {
|
|
3325
|
+
const start = first + i * width;
|
|
3326
|
+
const values = Array.from({ length: 6 }, (_v, j) => this.valueFor(name, start + width * j / 6, walk));
|
|
3327
|
+
const sum = values.reduce((a, v) => a + v, 0);
|
|
3328
|
+
return { bucketStart: new Date(start).toISOString(), name, avg: sum / values.length, min: Math.min(...values), max: Math.max(...values), sum, count: values.length };
|
|
3329
|
+
});
|
|
3330
|
+
});
|
|
3331
|
+
}
|
|
3235
3332
|
return names.map((name) => {
|
|
3236
3333
|
const walk = /* @__PURE__ */ new Map();
|
|
3237
3334
|
const values = Array.from({ length: 120 }, (_, i) => this.valueFor(name, from + (to - from) * i / 119, walk));
|
|
@@ -4178,6 +4275,11 @@ var RecordedDataSource = class {
|
|
|
4178
4275
|
const declared = this.rec.declaredMetrics;
|
|
4179
4276
|
return declared && Object.prototype.hasOwnProperty.call(declared, kind) ? declared[kind] : null;
|
|
4180
4277
|
}
|
|
4278
|
+
// The same for one device, through its recorded kind.
|
|
4279
|
+
async declaredMetricsForDevice(deviceToken) {
|
|
4280
|
+
const kind = this.kinds.get(deviceToken);
|
|
4281
|
+
return kind === void 0 ? null : this.declaredMetrics(kind);
|
|
4282
|
+
}
|
|
4181
4283
|
// Each device's seed comes from the recording itself, with no read to make: its newest reading per
|
|
4182
4284
|
// measurement inside the history window, and every measurement it reported in that window, which
|
|
4183
4285
|
// is how "does not report this" (a dozer's tyres) is told from "sent nothing".
|
|
@@ -5170,6 +5272,7 @@ function createDeviceResolver() {
|
|
|
5170
5272
|
const anchorCache = /* @__PURE__ */ new Map();
|
|
5171
5273
|
const memberCache = /* @__PURE__ */ new Map();
|
|
5172
5274
|
const existsCache = /* @__PURE__ */ new Map();
|
|
5275
|
+
const typeCache = /* @__PURE__ */ new Map();
|
|
5173
5276
|
let declaredBatch = null;
|
|
5174
5277
|
function anchorKey(anchor) {
|
|
5175
5278
|
return `${anchor.relationship}|${anchor.targetType}|${anchor.targetToken}`;
|
|
@@ -5257,6 +5360,19 @@ function createDeviceResolver() {
|
|
|
5257
5360
|
batch.set(deviceType, waiting);
|
|
5258
5361
|
});
|
|
5259
5362
|
},
|
|
5363
|
+
// The device type's token, from the same names read the roster uses. A failed read rejects (the
|
|
5364
|
+
// caller treats that as unknown) and is not cached.
|
|
5365
|
+
deviceType(deviceToken) {
|
|
5366
|
+
let pending = typeCache.get(deviceToken);
|
|
5367
|
+
if (!pending) {
|
|
5368
|
+
pending = gql3("device-management", DEVICE_NAMES, { tokens: [deviceToken] }).then((r) => r.devicesByToken.find((d) => d.token === deviceToken)?.deviceType?.token ?? null).catch((err) => {
|
|
5369
|
+
typeCache.delete(deviceToken);
|
|
5370
|
+
throw err;
|
|
5371
|
+
});
|
|
5372
|
+
typeCache.set(deviceToken, pending);
|
|
5373
|
+
}
|
|
5374
|
+
return pending;
|
|
5375
|
+
},
|
|
5260
5376
|
// deviceExists caches only a POSITIVE result (a live device is stable for the
|
|
5261
5377
|
// session); a negative and an error both drop the entry so a later check re-queries.
|
|
5262
5378
|
// ADR-042 frees a token on delete, so a deleted-then-recreated device must be able to
|
|
@@ -5318,7 +5434,8 @@ async function fetchWidgetHistory(widget, window2, options = {}) {
|
|
|
5318
5434
|
occurredTime: b.bucketStart,
|
|
5319
5435
|
name: b.name,
|
|
5320
5436
|
value: b.avg,
|
|
5321
|
-
classifier: null
|
|
5437
|
+
classifier: null,
|
|
5438
|
+
bucketSeconds: window2.intervalSeconds
|
|
5322
5439
|
})).sort((a, b) => a.occurredTime < b.occurredTime ? -1 : 1);
|
|
5323
5440
|
} catch (err) {
|
|
5324
5441
|
if (options.rethrow) throw err;
|
|
@@ -5541,7 +5658,7 @@ var CHANNELS = ["measurement", "alarm", "control", "selection", "location", "agg
|
|
|
5541
5658
|
var SEMVER2 = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
5542
5659
|
var SELECTOR_KINDS = ["device", "anchor", "slot"];
|
|
5543
5660
|
var BINDING_KEYS = {
|
|
5544
|
-
measurement: ["window", "windowSeconds", "members", "presence"],
|
|
5661
|
+
measurement: ["window", "windowSeconds", "members", "presence", "history"],
|
|
5545
5662
|
alarm: ["pageSize", "state", "severity", "acknowledged", "groupBy", "countBySeverity", "deviceType"],
|
|
5546
5663
|
control: ["pageSize"],
|
|
5547
5664
|
location: [],
|
|
@@ -5877,9 +5994,11 @@ function checkBinding(binding, channel, specs, add) {
|
|
|
5877
5994
|
}
|
|
5878
5995
|
}
|
|
5879
5996
|
};
|
|
5880
|
-
const presence
|
|
5881
|
-
|
|
5882
|
-
|
|
5997
|
+
for (const key of ["presence", "history"]) {
|
|
5998
|
+
const flag = binding[key];
|
|
5999
|
+
if (flag !== void 0 && !(isRecord(flag) && flag.const === true && Object.keys(flag).length === 1)) {
|
|
6000
|
+
add(`binding.${key}`, "must be { const: true }");
|
|
6001
|
+
}
|
|
5883
6002
|
}
|
|
5884
6003
|
modeBinding("members");
|
|
5885
6004
|
modeBinding("groupBy");
|
|
@@ -6061,6 +6180,7 @@ function effectiveLayout(def, containerWidth, options = {}) {
|
|
|
6061
6180
|
return { ...shape, grid };
|
|
6062
6181
|
}
|
|
6063
6182
|
export {
|
|
6183
|
+
ABSOLUTE_FUTURE_SKEW_MS,
|
|
6064
6184
|
ANCHOR_PAGE_SIZE,
|
|
6065
6185
|
BASE_BREAKPOINT,
|
|
6066
6186
|
BIND_PARAM_PREFIX,
|
|
@@ -6075,6 +6195,7 @@ export {
|
|
|
6075
6195
|
DENSITY_SCALE,
|
|
6076
6196
|
DashboardDefinitionError,
|
|
6077
6197
|
DashboardHub,
|
|
6198
|
+
EARLIEST_ABSOLUTE_MS,
|
|
6078
6199
|
FALLBACK_DEFAULT_SPAN,
|
|
6079
6200
|
FRAME_BORDER_WIDTHS,
|
|
6080
6201
|
FRAME_HEADERS,
|
|
@@ -6082,8 +6203,10 @@ export {
|
|
|
6082
6203
|
FRAME_VARIANTS,
|
|
6083
6204
|
HOST_OPTION_CONTROLS,
|
|
6084
6205
|
LEGACY_REFERENCE_WIDTH,
|
|
6206
|
+
MAX_ABSOLUTE_SPAN_SECONDS,
|
|
6085
6207
|
MAX_SEED_BUCKETS,
|
|
6086
6208
|
MAX_TIME_RANGE_SECONDS,
|
|
6209
|
+
MIN_ABSOLUTE_SPAN_SECONDS,
|
|
6087
6210
|
MIN_TIME_RANGE_SECONDS,
|
|
6088
6211
|
NotInRecordingError,
|
|
6089
6212
|
OFFLINE_AFTER_MS,
|
|
@@ -6114,6 +6237,9 @@ export {
|
|
|
6114
6237
|
WIDGET_CLIPBOARD_VERSION,
|
|
6115
6238
|
WIDGET_TYPES,
|
|
6116
6239
|
WidgetCatalogError,
|
|
6240
|
+
absoluteRange,
|
|
6241
|
+
absoluteRangeProblem,
|
|
6242
|
+
absoluteToParams,
|
|
6117
6243
|
activeBreakpoint,
|
|
6118
6244
|
addWidget,
|
|
6119
6245
|
anchorFraction,
|
|
@@ -6171,6 +6297,7 @@ export {
|
|
|
6171
6297
|
hasScopedSlots,
|
|
6172
6298
|
historyWindowFor,
|
|
6173
6299
|
initialTimeRange,
|
|
6300
|
+
isAbsolute,
|
|
6174
6301
|
isBuiltinWidget,
|
|
6175
6302
|
isBuiltinWidgetId,
|
|
6176
6303
|
isCancellableCommandStatus,
|
|
@@ -6184,16 +6311,19 @@ export {
|
|
|
6184
6311
|
layoutBreakpoints,
|
|
6185
6312
|
layoutRects,
|
|
6186
6313
|
layoutShape,
|
|
6314
|
+
leaveAbsolute,
|
|
6187
6315
|
lintLayout,
|
|
6188
6316
|
liveColumns,
|
|
6189
6317
|
migrateToSlots,
|
|
6190
6318
|
moveWidget,
|
|
6191
6319
|
numberSpec,
|
|
6192
6320
|
paddingPx,
|
|
6321
|
+
parseAbsoluteParams,
|
|
6193
6322
|
parseBindParams,
|
|
6194
6323
|
parseBindingManifest,
|
|
6195
6324
|
parseBoardRecording,
|
|
6196
6325
|
parseDashboardDefinition,
|
|
6326
|
+
parseInstantParam,
|
|
6197
6327
|
parsePausedParam,
|
|
6198
6328
|
parseRangeParam,
|
|
6199
6329
|
parseSlotBinding,
|
|
@@ -6250,6 +6380,7 @@ export {
|
|
|
6250
6380
|
storedDefinition,
|
|
6251
6381
|
stripDefaultBindings,
|
|
6252
6382
|
timeRangeFromSearch,
|
|
6383
|
+
timeRangeLinkFromSearch,
|
|
6253
6384
|
undoEdit,
|
|
6254
6385
|
unresolvedWidgets,
|
|
6255
6386
|
updateWidget,
|