@object-ui/core 6.0.4 → 6.2.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/CHANGELOG.md CHANGED
@@ -1,5 +1,36 @@
1
1
  # @object-ui/core
2
2
 
3
+ ## 6.2.0
4
+
5
+ ### Patch Changes
6
+
7
+ - @object-ui/types@6.2.0
8
+
9
+ ## 6.1.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 991b62d: Add `compareTo` field to dashboard widgets for period-over-period
14
+ comparison. Supports `'previousPeriod'`, `'previousYear'`, and
15
+ `{ offset: '7d' | '4w' | '1M' | '1y' }`.
16
+ - **Metric / gauge widgets** now compute a delta percentage when `compareTo`
17
+ is set and surface it as a derived `trend` (auto-labelled via
18
+ `dashboard.trend.vsLast*` i18n keys sniffed from the filter macros).
19
+ - **Chart widgets** (line / area / bar / horizontal-bar / scatter / combo)
20
+ overlay a muted comparison-period series (dashed line, lower fill opacity).
21
+ Pie / donut / funnel ignore `compareTo`.
22
+ - New core utilities: `shiftFilterByCompareTo`, `compareToTrendLabelKey`,
23
+ `computeMetricDelta`, and `CompareToConfig` type.
24
+ - `ChartSeries` now accepts `variant: 'comparison'`, `dashArray`, and
25
+ `opacity` overrides for visual treatment.
26
+
27
+ See `packages/plugin-dashboard/SKILL.md` for usage examples.
28
+
29
+ ### Patch Changes
30
+
31
+ - Updated dependencies [991b62d]
32
+ - @object-ui/types@6.1.0
33
+
3
34
  ## 6.0.4
4
35
 
5
36
  ### Patch Changes
@@ -120,6 +120,10 @@ export interface ActionDef {
120
120
  onSuccess?: ActionDef | ActionDef[];
121
121
  /** Callback on failure */
122
122
  onFailure?: ActionDef | ActionDef[];
123
+ /** When true, the runner pre-opens about:blank synchronously on click so the
124
+ * handler can drive it to a returned `redirectUrl` after an awaited fetch
125
+ * without tripping popup blockers. Used by actions like `sso_as_owner`. */
126
+ opensInNewTab?: boolean;
123
127
  /** Any additional properties */
124
128
  [key: string]: any;
125
129
  }
package/dist/index.d.ts CHANGED
@@ -37,3 +37,4 @@ export * from './protocols/index.js';
37
37
  export { composeStacks } from '@objectstack/spec';
38
38
  export * from './utils/drill-down.js';
39
39
  export * from './utils/date-macros.js';
40
+ export * from './utils/compare-to.js';
package/dist/index.js CHANGED
@@ -36,3 +36,4 @@ export * from './protocols/index.js';
36
36
  export { composeStacks } from '@objectstack/spec';
37
37
  export * from './utils/drill-down.js';
38
38
  export * from './utils/date-macros.js';
39
+ export * from './utils/compare-to.js';
@@ -0,0 +1,36 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ /**
9
+ * Period-over-period comparison config for dashboard widgets.
10
+ *
11
+ * - `'previousPeriod'` — substitute `current_*` / `today` date macro tokens
12
+ * with their `last_*` / `yesterday` counterparts (e.g. `current_quarter_start`
13
+ * → `last_quarter_start`). Best when the filter uses date macros.
14
+ * - `'previousYear'` — re-resolve date macros against a `now` shifted back
15
+ * one calendar year (same week / month / quarter, one year earlier).
16
+ * - `{ offset: '7d' | '4w' | '1M' | '1y' }` — re-resolve macros against a
17
+ * `now` shifted by the given duration. Units: `d` (day), `w` (week),
18
+ * `M` (month), `y` (year).
19
+ */
20
+ export type CompareToConfig = 'previousPeriod' | 'previousYear' | {
21
+ offset: string;
22
+ };
23
+ /**
24
+ * Resolve a filter for a period-over-period comparison query.
25
+ *
26
+ * - `previousYear` — re-resolve date macros against a `now` shifted back by one year.
27
+ * - `{ offset }` — re-resolve date macros against a `now` shifted by the given duration.
28
+ * - `previousPeriod` — substitute `current_*` / `today` tokens with `last_*` / `yesterday`
29
+ * before resolving.
30
+ */
31
+ export declare function shiftFilterByCompareTo<T = any>(filter: T, compareTo: CompareToConfig, now?: Date): T;
32
+ /**
33
+ * Derive a translation key suffix (under `dashboard.trend.*`) describing the
34
+ * comparison window. Used by metric widgets to label the trend delta.
35
+ */
36
+ export declare function compareToTrendLabelKey(compareTo: CompareToConfig, filter?: unknown): string;
@@ -0,0 +1,112 @@
1
+ /**
2
+ * ObjectUI
3
+ * Copyright (c) 2024-present ObjectStack Inc.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ import { resolveDateMacros } from './date-macros.js';
9
+ const CURRENT_TO_LAST_TOKENS = {
10
+ current_week_start: 'last_week_start',
11
+ current_week_end: 'last_week_end',
12
+ current_month_start: 'last_month_start',
13
+ current_month_end: 'last_month_end',
14
+ current_quarter_start: 'last_quarter_start',
15
+ current_quarter_end: 'last_quarter_end',
16
+ current_year_start: 'last_year_start',
17
+ current_year_end: 'last_year_end',
18
+ week_start: 'last_week_start',
19
+ week_end: 'last_week_end',
20
+ month_start: 'last_month_start',
21
+ month_end: 'last_month_end',
22
+ quarter_start: 'last_quarter_start',
23
+ quarter_end: 'last_quarter_end',
24
+ year_start: 'last_year_start',
25
+ year_end: 'last_year_end',
26
+ today: 'yesterday',
27
+ };
28
+ function substituteTokens(value, map) {
29
+ if (value == null)
30
+ return value;
31
+ if (typeof value === 'string') {
32
+ return value.replace(/\$?\{([a-zA-Z0-9_]+)\}/g, (m, tok) => {
33
+ const target = map[tok];
34
+ return target ? `{${target}}` : m;
35
+ });
36
+ }
37
+ if (Array.isArray(value))
38
+ return value.map((v) => substituteTokens(v, map));
39
+ if (typeof value === 'object') {
40
+ const out = {};
41
+ for (const k of Object.keys(value))
42
+ out[k] = substituteTokens(value[k], map);
43
+ return out;
44
+ }
45
+ return value;
46
+ }
47
+ function shiftNow(now, offset) {
48
+ const m = offset.match(/^(\d+)([dwMy])$/);
49
+ if (!m)
50
+ return null;
51
+ const n = parseInt(m[1], 10);
52
+ const unit = m[2];
53
+ const x = new Date(now);
54
+ if (unit === 'd')
55
+ x.setDate(x.getDate() - n);
56
+ else if (unit === 'w')
57
+ x.setDate(x.getDate() - n * 7);
58
+ else if (unit === 'M')
59
+ x.setMonth(x.getMonth() - n);
60
+ else if (unit === 'y')
61
+ x.setFullYear(x.getFullYear() - n);
62
+ else
63
+ return null;
64
+ return x;
65
+ }
66
+ /**
67
+ * Resolve a filter for a period-over-period comparison query.
68
+ *
69
+ * - `previousYear` — re-resolve date macros against a `now` shifted back by one year.
70
+ * - `{ offset }` — re-resolve date macros against a `now` shifted by the given duration.
71
+ * - `previousPeriod` — substitute `current_*` / `today` tokens with `last_*` / `yesterday`
72
+ * before resolving.
73
+ */
74
+ export function shiftFilterByCompareTo(filter, compareTo, now = new Date()) {
75
+ if (compareTo === 'previousYear') {
76
+ const shifted = new Date(now.getFullYear() - 1, now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
77
+ return resolveDateMacros(filter, shifted);
78
+ }
79
+ if (typeof compareTo === 'object' && compareTo && 'offset' in compareTo) {
80
+ const shifted = shiftNow(now, compareTo.offset);
81
+ if (!shifted)
82
+ return resolveDateMacros(filter, now);
83
+ return resolveDateMacros(filter, shifted);
84
+ }
85
+ // previousPeriod
86
+ const substituted = substituteTokens(filter, CURRENT_TO_LAST_TOKENS);
87
+ return resolveDateMacros(substituted, now);
88
+ }
89
+ /**
90
+ * Derive a translation key suffix (under `dashboard.trend.*`) describing the
91
+ * comparison window. Used by metric widgets to label the trend delta.
92
+ */
93
+ export function compareToTrendLabelKey(compareTo, filter) {
94
+ if (compareTo === 'previousYear')
95
+ return 'vsLastYear';
96
+ if (typeof compareTo === 'object' && compareTo && 'offset' in compareTo) {
97
+ return 'vsPreviousPeriod';
98
+ }
99
+ // previousPeriod — sniff the dominant token in the filter
100
+ const json = filter ? JSON.stringify(filter) : '';
101
+ if (/current_year_|year_start|year_end/.test(json))
102
+ return 'vsLastYear';
103
+ if (/current_quarter_|quarter_start|quarter_end/.test(json))
104
+ return 'vsLastQuarter';
105
+ if (/current_month_|month_start|month_end/.test(json))
106
+ return 'vsLastMonth';
107
+ if (/current_week_|week_start|week_end/.test(json))
108
+ return 'vsLastWeek';
109
+ if (/\btoday\b/.test(json))
110
+ return 'vsYesterday';
111
+ return 'vsPreviousPeriod';
112
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/core",
3
- "version": "6.0.4",
3
+ "version": "6.2.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",
@@ -25,14 +25,14 @@
25
25
  }
26
26
  },
27
27
  "dependencies": {
28
- "@objectstack/spec": "^5.2.0",
28
+ "@objectstack/spec": "^6.7.1",
29
29
  "lodash": "^4.18.1",
30
30
  "zod": "^4.4.3",
31
- "@object-ui/types": "6.0.4"
31
+ "@object-ui/types": "6.2.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "typescript": "^6.0.3",
35
- "vitest": "^4.1.6"
35
+ "vitest": "^4.1.7"
36
36
  },
37
37
  "keywords": [
38
38
  "objectui",