@formant/ava 3.5.0-formant → 3.5.2-formant

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.
@@ -1,6 +1,6 @@
1
1
  import { __read, __spreadArray } from "tslib";
2
2
  import { size } from 'lodash';
3
- import { dataFormat } from '../../../../utils';
3
+ import { dataFormat, formatInsightDate } from '../../../../utils';
4
4
  import { pointMarkStrategy } from '../commonMarks';
5
5
  import { insight2ChartStrategy } from '../chart';
6
6
  import { augmentedMarks2Marks } from '../../utils';
@@ -14,7 +14,7 @@ export var changePointAugmentedMarksStrategy = function (insight) {
14
14
  pointMarkStrategy([pattern], {
15
15
  role: 'highlight',
16
16
  name: 'change point',
17
- label: function (pt) { return "".concat(pt.x, ", ").concat(measure, ": ").concat(dataFormat(pt.y)); },
17
+ label: function (pt) { return "".concat(formatInsightDate(pt.x), " \u00B7 ").concat(measure, ": ").concat(dataFormat(pt.y)); },
18
18
  }),
19
19
  ],
20
20
  }); });
@@ -2,6 +2,7 @@ import { __extends } from "tslib";
2
2
  /* eslint-disable no-template-curly-in-string */
3
3
  import { first, last } from 'lodash';
4
4
  import { generateTextSpec } from '../../../ntv';
5
+ import { formatInsightDateRange } from '../../../utils/dateFormat';
5
6
  import { InsightNarrativeStrategy } from './base';
6
7
  var variableMetaMap = {
7
8
  dateRange: {
@@ -25,7 +26,7 @@ var ChangePointNarrativeStrategy = /** @class */ (function (_super) {
25
26
  var spec = generateTextSpec({
26
27
  structures: ChangePointNarrativeStrategy.structures[lang],
27
28
  variable: {
28
- dateRange: "".concat(first(data)[dimension], "~").concat(last(data)[dimension]),
29
+ dateRange: formatInsightDateRange(first(data)[dimension], last(data)[dimension]),
29
30
  measure: patterns[0].measure,
30
31
  total: patterns.length,
31
32
  },
@@ -4,8 +4,7 @@ import { first, last, maxBy, minBy } from 'lodash';
4
4
  import { generateTextSpec } from '../../../ntv';
5
5
  import { InsightNarrativeStrategy } from './base';
6
6
  import { getDiffDesc } from './helpers';
7
- import { formatDateRange } from "little-date";
8
- import { format } from 'date-fns';
7
+ import { formatInsightDate, formatInsightDateRange } from '../../../utils/dateFormat';
9
8
  var variableMetaMap = {
10
9
  dateRange: {
11
10
  varType: 'time_desc',
@@ -46,7 +45,7 @@ var TimeSeriesOutlierNarrativeStrategy = /** @class */ (function (_super) {
46
45
  var spec = generateTextSpec({
47
46
  structures: TimeSeriesOutlierNarrativeStrategy.structures[lang],
48
47
  variable: {
49
- dateRange: "".concat(formatDateRange(new Date(first(data)[dimension]), new Date(last(data)[dimension]), { includeTime: false })),
48
+ dateRange: formatInsightDateRange(first(data)[dimension], last(data)[dimension]),
50
49
  total: patterns.length,
51
50
  measure: measure,
52
51
  max: maxBy(data, measure)[measure],
@@ -54,7 +53,7 @@ var TimeSeriesOutlierNarrativeStrategy = /** @class */ (function (_super) {
54
53
  outliers: patterns.map(function (point) {
55
54
  var base = point.baselines[point.index];
56
55
  var diff = point.y - base;
57
- return __assign(__assign({}, point), { base: base, diffDesc: getDiffDesc(diff, lang), x: format(new Date(point.x), 'MMM d, yyyy'), diff: diff });
56
+ return __assign(__assign({}, point), { base: base, diffDesc: getDiffDesc(diff, lang), x: formatInsightDate(point.x), diff: diff });
58
57
  }),
59
58
  },
60
59
  });
@@ -2,8 +2,8 @@ import { __extends } from "tslib";
2
2
  /* eslint-disable no-template-curly-in-string */
3
3
  import { first, last } from 'lodash';
4
4
  import { generateTextSpec } from '../../../ntv';
5
+ import { formatInsightDateRange } from '../../../utils/dateFormat';
5
6
  import { InsightNarrativeStrategy } from './base';
6
- import { formatDateRange } from "little-date";
7
7
  var trendMapping = {
8
8
  decreasing: '下降',
9
9
  increasing: '上升',
@@ -32,7 +32,7 @@ var TrendNarrativeStrategy = /** @class */ (function (_super) {
32
32
  var spec = generateTextSpec({
33
33
  structures: TrendNarrativeStrategy.structures[lang],
34
34
  variable: {
35
- dateRange: "".concat(formatDateRange(new Date(first(data)[dimension]), new Date(last(data)[dimension]), { includeTime: false })),
35
+ dateRange: formatInsightDateRange(first(data)[dimension], last(data)[dimension]),
36
36
  measure: measure,
37
37
  trend: lang === 'en-US' ? trend : trendMapping[trend],
38
38
  slope: regression.equation[0],
@@ -0,0 +1,44 @@
1
+ import { format } from 'date-fns';
2
+ import { formatDateRange } from 'little-date';
3
+ // 2025-03-19, 2025-03-19 00:00:00, 2025-03-19T00:00:00.000Z, 2025-03-19T00:00:00+02:00
4
+ var ISO_LIKE = /^\d{4}-\d{2}-\d{2}(?:[ T]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;
5
+ /**
6
+ * Parse an insight dimension value as a date. Only ISO-like strings and Date objects count;
7
+ * zone-less values are local time. `new Date('2025-03-19 00:00:00')` is non-standard (older
8
+ * Safari rejects it), so the space is normalised to `T` first.
9
+ */
10
+ export var parseInsightDate = function (value) {
11
+ if (value instanceof Date)
12
+ return Number.isNaN(value.getTime()) ? undefined : value;
13
+ if (typeof value !== 'string' || !ISO_LIKE.test(value))
14
+ return undefined;
15
+ var date = new Date(value.length === 10 ? "".concat(value, "T00:00:00") : value.replace(' ', 'T'));
16
+ return Number.isNaN(date.getTime()) ? undefined : date;
17
+ };
18
+ // a zone designator means an absolute instant (e.g. an hourly UTC bucket): always show its time
19
+ var ZONED = /\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})$/;
20
+ /**
21
+ * Whether to print a time of day. Zoned instants always do, so an hourly series reads
22
+ * `Oct 6, 23:00`, `Oct 7, 00:00` rather than switching to a date at local midnight. Zone-less
23
+ * values only do when the clock is not midnight (`2025-03-19 00:00:00` is a daily bucket).
24
+ */
25
+ var showsTime = function (value, date) {
26
+ return value instanceof Date || (typeof value === 'string' && ZONED.test(value))
27
+ ? true
28
+ : date.getHours() !== 0 || date.getMinutes() !== 0;
29
+ };
30
+ /** `Oct 7, 2026`, or `Oct 7, 14:00` when the value carries a time of day; non-dates pass through */
31
+ export var formatInsightDate = function (value) {
32
+ var date = parseInsightDate(value);
33
+ if (!date)
34
+ return String(value);
35
+ return format(date, showsTime(value, date) ? 'MMM d, HH:mm' : 'MMM d, yyyy');
36
+ };
37
+ /** `Oct 6 - 7, 2026` style range (little-date); non-dates fall back to `start ~ end` */
38
+ export var formatInsightDateRange = function (start, end) {
39
+ var from = parseInsightDate(start);
40
+ var to = parseInsightDate(end);
41
+ if (!from || !to)
42
+ return "".concat(start, "~").concat(end);
43
+ return formatDateRange(from, to, { includeTime: false });
44
+ };
@@ -1,3 +1,4 @@
1
1
  export * from './isType';
2
2
  export * from './arr2map';
3
3
  export { default as dataFormat } from './dataFormat';
4
+ export { parseInsightDate, formatInsightDate, formatInsightDateRange } from './dateFormat';
@@ -17,7 +17,7 @@ var changePointAugmentedMarksStrategy = function (insight) {
17
17
  (0, commonMarks_1.pointMarkStrategy)([pattern], {
18
18
  role: 'highlight',
19
19
  name: 'change point',
20
- label: function (pt) { return "".concat(pt.x, ", ").concat(measure, ": ").concat((0, utils_1.dataFormat)(pt.y)); },
20
+ label: function (pt) { return "".concat((0, utils_1.formatInsightDate)(pt.x), " \u00B7 ").concat(measure, ": ").concat((0, utils_1.dataFormat)(pt.y)); },
21
21
  }),
22
22
  ],
23
23
  }); });
@@ -4,6 +4,7 @@ var tslib_1 = require("tslib");
4
4
  /* eslint-disable no-template-curly-in-string */
5
5
  var lodash_1 = require("lodash");
6
6
  var ntv_1 = require("../../../ntv");
7
+ var dateFormat_1 = require("../../../utils/dateFormat");
7
8
  var base_1 = require("./base");
8
9
  var variableMetaMap = {
9
10
  dateRange: {
@@ -27,7 +28,7 @@ var ChangePointNarrativeStrategy = /** @class */ (function (_super) {
27
28
  var spec = (0, ntv_1.generateTextSpec)({
28
29
  structures: ChangePointNarrativeStrategy.structures[lang],
29
30
  variable: {
30
- dateRange: "".concat((0, lodash_1.first)(data)[dimension], "~").concat((0, lodash_1.last)(data)[dimension]),
31
+ dateRange: (0, dateFormat_1.formatInsightDateRange)((0, lodash_1.first)(data)[dimension], (0, lodash_1.last)(data)[dimension]),
31
32
  measure: patterns[0].measure,
32
33
  total: patterns.length,
33
34
  },
@@ -6,8 +6,7 @@ var lodash_1 = require("lodash");
6
6
  var ntv_1 = require("../../../ntv");
7
7
  var base_1 = require("./base");
8
8
  var helpers_1 = require("./helpers");
9
- var little_date_1 = require("little-date");
10
- var date_fns_1 = require("date-fns");
9
+ var dateFormat_1 = require("../../../utils/dateFormat");
11
10
  var variableMetaMap = {
12
11
  dateRange: {
13
12
  varType: 'time_desc',
@@ -48,7 +47,7 @@ var TimeSeriesOutlierNarrativeStrategy = /** @class */ (function (_super) {
48
47
  var spec = (0, ntv_1.generateTextSpec)({
49
48
  structures: TimeSeriesOutlierNarrativeStrategy.structures[lang],
50
49
  variable: {
51
- dateRange: "".concat((0, little_date_1.formatDateRange)(new Date((0, lodash_1.first)(data)[dimension]), new Date((0, lodash_1.last)(data)[dimension]), { includeTime: false })),
50
+ dateRange: (0, dateFormat_1.formatInsightDateRange)((0, lodash_1.first)(data)[dimension], (0, lodash_1.last)(data)[dimension]),
52
51
  total: patterns.length,
53
52
  measure: measure,
54
53
  max: (0, lodash_1.maxBy)(data, measure)[measure],
@@ -56,7 +55,7 @@ var TimeSeriesOutlierNarrativeStrategy = /** @class */ (function (_super) {
56
55
  outliers: patterns.map(function (point) {
57
56
  var base = point.baselines[point.index];
58
57
  var diff = point.y - base;
59
- return tslib_1.__assign(tslib_1.__assign({}, point), { base: base, diffDesc: (0, helpers_1.getDiffDesc)(diff, lang), x: (0, date_fns_1.format)(new Date(point.x), 'MMM d, yyyy'), diff: diff });
58
+ return tslib_1.__assign(tslib_1.__assign({}, point), { base: base, diffDesc: (0, helpers_1.getDiffDesc)(diff, lang), x: (0, dateFormat_1.formatInsightDate)(point.x), diff: diff });
60
59
  }),
61
60
  },
62
61
  });
@@ -4,8 +4,8 @@ var tslib_1 = require("tslib");
4
4
  /* eslint-disable no-template-curly-in-string */
5
5
  var lodash_1 = require("lodash");
6
6
  var ntv_1 = require("../../../ntv");
7
+ var dateFormat_1 = require("../../../utils/dateFormat");
7
8
  var base_1 = require("./base");
8
- var little_date_1 = require("little-date");
9
9
  var trendMapping = {
10
10
  decreasing: '下降',
11
11
  increasing: '上升',
@@ -34,7 +34,7 @@ var TrendNarrativeStrategy = /** @class */ (function (_super) {
34
34
  var spec = (0, ntv_1.generateTextSpec)({
35
35
  structures: TrendNarrativeStrategy.structures[lang],
36
36
  variable: {
37
- dateRange: "".concat((0, little_date_1.formatDateRange)(new Date((0, lodash_1.first)(data)[dimension]), new Date((0, lodash_1.last)(data)[dimension]), { includeTime: false })),
37
+ dateRange: (0, dateFormat_1.formatInsightDateRange)((0, lodash_1.first)(data)[dimension], (0, lodash_1.last)(data)[dimension]),
38
38
  measure: measure,
39
39
  trend: lang === 'en-US' ? trend : trendMapping[trend],
40
40
  slope: regression.equation[0],
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Parse an insight dimension value as a date. Only ISO-like strings and Date objects count;
3
+ * zone-less values are local time. `new Date('2025-03-19 00:00:00')` is non-standard (older
4
+ * Safari rejects it), so the space is normalised to `T` first.
5
+ */
6
+ export declare const parseInsightDate: (value: unknown) => Date | undefined;
7
+ /** `Oct 7, 2026`, or `Oct 7, 14:00` when the value carries a time of day; non-dates pass through */
8
+ export declare const formatInsightDate: (value: unknown) => string;
9
+ /** `Oct 6 - 7, 2026` style range (little-date); non-dates fall back to `start ~ end` */
10
+ export declare const formatInsightDateRange: (start: unknown, end: unknown) => string;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatInsightDateRange = exports.formatInsightDate = exports.parseInsightDate = void 0;
4
+ var date_fns_1 = require("date-fns");
5
+ var little_date_1 = require("little-date");
6
+ // 2025-03-19, 2025-03-19 00:00:00, 2025-03-19T00:00:00.000Z, 2025-03-19T00:00:00+02:00
7
+ var ISO_LIKE = /^\d{4}-\d{2}-\d{2}(?:[ T]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;
8
+ /**
9
+ * Parse an insight dimension value as a date. Only ISO-like strings and Date objects count;
10
+ * zone-less values are local time. `new Date('2025-03-19 00:00:00')` is non-standard (older
11
+ * Safari rejects it), so the space is normalised to `T` first.
12
+ */
13
+ var parseInsightDate = function (value) {
14
+ if (value instanceof Date)
15
+ return Number.isNaN(value.getTime()) ? undefined : value;
16
+ if (typeof value !== 'string' || !ISO_LIKE.test(value))
17
+ return undefined;
18
+ var date = new Date(value.length === 10 ? "".concat(value, "T00:00:00") : value.replace(' ', 'T'));
19
+ return Number.isNaN(date.getTime()) ? undefined : date;
20
+ };
21
+ exports.parseInsightDate = parseInsightDate;
22
+ // a zone designator means an absolute instant (e.g. an hourly UTC bucket): always show its time
23
+ var ZONED = /\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:?\d{2})$/;
24
+ /**
25
+ * Whether to print a time of day. Zoned instants always do, so an hourly series reads
26
+ * `Oct 6, 23:00`, `Oct 7, 00:00` rather than switching to a date at local midnight. Zone-less
27
+ * values only do when the clock is not midnight (`2025-03-19 00:00:00` is a daily bucket).
28
+ */
29
+ var showsTime = function (value, date) {
30
+ return value instanceof Date || (typeof value === 'string' && ZONED.test(value))
31
+ ? true
32
+ : date.getHours() !== 0 || date.getMinutes() !== 0;
33
+ };
34
+ /** `Oct 7, 2026`, or `Oct 7, 14:00` when the value carries a time of day; non-dates pass through */
35
+ var formatInsightDate = function (value) {
36
+ var date = (0, exports.parseInsightDate)(value);
37
+ if (!date)
38
+ return String(value);
39
+ return (0, date_fns_1.format)(date, showsTime(value, date) ? 'MMM d, HH:mm' : 'MMM d, yyyy');
40
+ };
41
+ exports.formatInsightDate = formatInsightDate;
42
+ /** `Oct 6 - 7, 2026` style range (little-date); non-dates fall back to `start ~ end` */
43
+ var formatInsightDateRange = function (start, end) {
44
+ var from = (0, exports.parseInsightDate)(start);
45
+ var to = (0, exports.parseInsightDate)(end);
46
+ if (!from || !to)
47
+ return "".concat(start, "~").concat(end);
48
+ return (0, little_date_1.formatDateRange)(from, to, { includeTime: false });
49
+ };
50
+ exports.formatInsightDateRange = formatInsightDateRange;
@@ -1,3 +1,4 @@
1
1
  export * from './isType';
2
2
  export * from './arr2map';
3
3
  export { default as dataFormat } from './dataFormat';
4
+ export { parseInsightDate, formatInsightDate, formatInsightDateRange } from './dateFormat';
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.dataFormat = void 0;
3
+ exports.formatInsightDateRange = exports.formatInsightDate = exports.parseInsightDate = exports.dataFormat = void 0;
4
4
  var tslib_1 = require("tslib");
5
5
  tslib_1.__exportStar(require("./isType"), exports);
6
6
  tslib_1.__exportStar(require("./arr2map"), exports);
7
7
  var dataFormat_1 = require("./dataFormat");
8
8
  Object.defineProperty(exports, "dataFormat", { enumerable: true, get: function () { return tslib_1.__importDefault(dataFormat_1).default; } });
9
+ var dateFormat_1 = require("./dateFormat");
10
+ Object.defineProperty(exports, "parseInsightDate", { enumerable: true, get: function () { return dateFormat_1.parseInsightDate; } });
11
+ Object.defineProperty(exports, "formatInsightDate", { enumerable: true, get: function () { return dateFormat_1.formatInsightDate; } });
12
+ Object.defineProperty(exports, "formatInsightDateRange", { enumerable: true, get: function () { return dateFormat_1.formatInsightDateRange; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formant/ava",
3
- "version": "3.5.0-formant",
3
+ "version": "3.5.2-formant",
4
4
  "description": "A framework for automated visual analytics.",
5
5
  "author": {
6
6
  "name": "formant",