@nethru/kit 1.0.3 → 1.0.5

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.
Files changed (3) hide show
  1. package/dist/index.esm.js +1083 -1102
  2. package/dist/index.js +1083 -1100
  3. package/package.json +1 -1
package/dist/index.esm.js CHANGED
@@ -1,1016 +1,232 @@
1
- import React$1, { useMemo, useState, useEffect, useCallback, createContext, useContext, useRef } from 'react';
2
- import Highcharts$1 from 'highcharts';
3
- import HighchartsReact from 'highcharts-react-official';
4
- import highchartsAccessibility from 'highcharts/modules/accessibility';
5
- import highchartsAnnotations from 'highcharts/modules/annotations';
6
- import { blue, purple, green, yellow, red, orange, lime, grey } from '@nethru/ui/base/colors';
1
+ import React$1, { useMemo, createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';
7
2
  import { alpha, Box, keyframes, Stack, TextField, FormControl, Select, MenuItem, IconButton } from '@mui/material';
8
3
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+ import Highcharts from 'highcharts';
5
+ import HighchartsReact from 'highcharts-react-official';
6
+ import 'highcharts/modules/pattern-fill.js';
7
+ import highchartsAccessibility from 'highcharts/modules/accessibility.js';
8
+ import highchartsAnnotations from 'highcharts/modules/annotations.js';
9
+ import { blue, purple, green, yellow, red, orange, lime, grey } from '@nethru/ui/base/colors/index.js';
9
10
  import { Send } from '@mui/icons-material';
10
11
 
11
- function getDefaultExportFromCjs (x) {
12
- return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
12
+ let globalConfig = {
13
+ apiUrl: ''
14
+ };
15
+ function configure$1(config) {
16
+ globalConfig = {
17
+ ...globalConfig,
18
+ ...config
19
+ };
13
20
  }
21
+ function getConfig() {
22
+ return globalConfig;
23
+ }
24
+
25
+ function ok$1() {}
14
26
 
15
- var patternFill = {exports: {}};
27
+ function unreachable() {}
16
28
 
17
29
  /**
18
- * Highcharts JS v11.3.0 (2024-01-10)
19
- *
20
- * Module for adding patterns and images as point fills.
30
+ * @typedef Options
31
+ * Configuration for `stringify`.
32
+ * @property {boolean} [padLeft=true]
33
+ * Whether to pad a space before a token.
34
+ * @property {boolean} [padRight=false]
35
+ * Whether to pad a space after a token.
36
+ */
37
+
38
+
39
+ /**
40
+ * Serialize an array of strings or numbers to comma-separated tokens.
21
41
  *
22
- * (c) 2010-2024 Highsoft AS
23
- * Author: Torstein Hønsi, Øystein Moseng
42
+ * @param {Array<string|number>} values
43
+ * List of tokens.
44
+ * @param {Options} [options]
45
+ * Configuration for `stringify` (optional).
46
+ * @returns {string}
47
+ * Comma-separated tokens.
48
+ */
49
+ function stringify$1(values, options) {
50
+ const settings = {};
51
+
52
+ // Ensure the last empty entry is seen.
53
+ const input = values[values.length - 1] === '' ? [...values, ''] : values;
54
+
55
+ return input
56
+ .join(
57
+ (settings.padRight ? ' ' : '') +
58
+ ',' +
59
+ (settings.padLeft === false ? '' : ' ')
60
+ )
61
+ .trim()
62
+ }
63
+
64
+ /**
65
+ * @typedef Options
66
+ * Configuration.
67
+ * @property {boolean | null | undefined} [jsx=false]
68
+ * Support JSX identifiers (default: `false`).
69
+ */
70
+
71
+ const nameRe = /^[$_\p{ID_Start}][$_\u{200C}\u{200D}\p{ID_Continue}]*$/u;
72
+ const nameReJsx = /^[$_\p{ID_Start}][-$_\u{200C}\u{200D}\p{ID_Continue}]*$/u;
73
+
74
+ /** @type {Options} */
75
+ const emptyOptions$2 = {};
76
+
77
+ /**
78
+ * Checks if the given value is a valid identifier name.
24
79
  *
25
- * License: www.highcharts.com/license
80
+ * @param {string} name
81
+ * Identifier to check.
82
+ * @param {Options | null | undefined} [options]
83
+ * Configuration (optional).
84
+ * @returns {boolean}
85
+ * Whether `name` can be an identifier.
86
+ */
87
+ function name(name, options) {
88
+ const settings = emptyOptions$2;
89
+ const re = settings.jsx ? nameReJsx : nameRe;
90
+ return re.test(name)
91
+ }
92
+
93
+ /**
94
+ * @typedef {import('hast').Nodes} Nodes
26
95
  */
27
96
 
28
- var hasRequiredPatternFill;
97
+ // HTML whitespace expression.
98
+ // See <https://infra.spec.whatwg.org/#ascii-whitespace>.
99
+ const re = /[ \t\n\f\r]/g;
29
100
 
30
- function requirePatternFill () {
31
- if (hasRequiredPatternFill) return patternFill.exports;
32
- hasRequiredPatternFill = 1;
33
- (function (module) {
34
- !function(t){module.exports?(t.default=t,module.exports=t):t("undefined"!=typeof Highcharts?Highcharts:void 0);}(function(t){var e=t?t._modules:{};function r(t,e,r,i){t.hasOwnProperty(e)||(t[e]=i.apply(null,r),"function"==typeof CustomEvent&&window.dispatchEvent(new CustomEvent("HighchartsModuleLoaded",{detail:{path:e,module:t[e]}})));}r(e,"Extensions/PatternFill.js",[e["Core/Animation/AnimationUtilities.js"],e["Core/Defaults.js"],e["Core/Globals.js"],e["Core/Utilities.js"]],function(t,e,r,i){let{animObject:a}=t,{getOptions:o}=e,{composed:n}=r,{addEvent:s,defined:h,erase:l,extend:p,merge:c,pick:d,pushUnique:f,removeEvent:u,wrap:g}=i,m=function(){let t=[],e=o().colors,r=0;for(let i of ["M 0 0 L 5 5 M 4.5 -0.5 L 5.5 0.5 M -0.5 4.5 L 0.5 5.5","M 0 5 L 5 0 M -0.5 0.5 L 0.5 -0.5 M 4.5 5.5 L 5.5 4.5","M 2 0 L 2 5 M 4 0 L 4 5","M 0 2 L 5 2 M 0 4 L 5 4","M 0 1.5 L 2.5 1.5 L 2.5 0 M 2.5 5 L 2.5 3.5 L 5 3.5"])t.push({path:i,color:e[r++],width:5,height:5,patternTransform:"scale(1.4 1.4)"});for(let i of(r=5,["M 0 0 L 5 10 L 10 0","M 3 3 L 8 3 L 8 8 L 3 8 Z","M 5 5 m -4 0 a 4 4 0 1 1 8 0 a 4 4 0 1 1 -8 0","M 0 0 L 10 10 M 9 -1 L 11 1 M -1 9 L 1 11","M 0 10 L 10 0 M -1 1 L 1 -1 M 9 11 L 11 9"]))t.push({path:i,color:e[r],width:10,height:10}),r+=5;return t}();function y(t,e){let r=JSON.stringify(t),i=r.length||0,a=0,o=0,n;if(e){n=Math.max(Math.floor(i/500),1);for(let t=0;t<i;t+=n)a+=r.charCodeAt(t);a&=a;}for(;o<i;++o)a=(a<<5)-a+r.charCodeAt(o),a&=a;return a.toString(16).replace("-","1")}function x(){if(this.renderer&&(this.renderer.defIds||[]).filter(t=>t&&t.indexOf&&0===t.indexOf("highcharts-pattern-")).length){for(let t of this.series)if(t.visible)for(let e of t.points){let t=e.options&&e.options.color;t&&t.pattern&&(t.pattern._width="defer",t.pattern._height="defer");}this.redraw(false);}}function w(){let t={},e=this.renderer,r=(e.defIds||[]).filter(t=>t.indexOf&&0===t.indexOf("highcharts-pattern-"));if(r.length)for(let i of([].forEach.call(this.renderTo.querySelectorAll('[color^="url("], [fill^="url("], [stroke^="url("]'),r=>{let i=r.getAttribute("fill")||r.getAttribute("color")||r.getAttribute("stroke");if(i){let r=i.replace(e.url,"").replace("url(#","").replace(")","");t[r]=true;}}),r))!t[i]&&(l(e.defIds,i),e.patternElements[i]&&(e.patternElements[i].destroy(),delete e.patternElements[i]));}function M(){let t=this.options.color;t&&t.pattern&&("string"==typeof t.pattern.path&&(t.pattern.path={d:t.pattern.path}),this.color=this.options.color=c(this.series.options.color,t));}function L(t){let e=t.args[0],r=t.args[1],i=t.args[2],a=this.chartIndex||0,o=e.pattern,n="#333333";if(void 0!==e.patternIndex&&m&&(o=m[e.patternIndex]),!o)return true;if(o.image||"string"==typeof o.path||o.path&&o.path.d){let t=i.parentNode&&i.parentNode.getAttribute("class");t=t&&t.indexOf("highcharts-legend")>-1,("defer"===o._width||"defer"===o._height)&&_.call({graphic:{element:i}},o),(t||!o.id)&&((o=c({},o)).id="highcharts-pattern-"+a+"-"+y(o)+y(o,true)),this.addPattern(o,!this.forExport&&d(o.animation,this.globalAnimation,{duration:100})),n=`url(${this.url}#${o.id+(this.forExport?"-export":"")})`;}else n=o.color||n;return i.setAttribute(r,n),e.toString=function(){return n},false}function b(){let t=this.chart.isResizing;if(this.isDirtyData||t||!this.chart.hasRendered)for(let e of this.points){let r=e.options&&e.options.color;r&&r.pattern&&(t&&!(e.shapeArgs&&e.shapeArgs.width&&e.shapeArgs.height)?(r.pattern._width="defer",r.pattern._height="defer"):e.calculatePatternDimensions(r.pattern));}}function _(t){if(t.width&&t.height)return;let e=this.graphic&&(this.graphic.getBBox&&this.graphic.getBBox(true)||this.graphic.element&&this.graphic.element.getBBox())||{},r=this.shapeArgs;if(r&&(e.width=r.width||e.width,e.height=r.height||e.height,e.x=r.x||e.x,e.y=r.y||e.y),t.image){if(!e.width||!e.height){t._width="defer",t._height="defer";let e=this.series.chart.mapView&&this.series.chart.mapView.getSVGTransform().scaleY;h(e)&&e<0&&(t._inverted=true);return}t.aspectRatio&&(e.aspectRatio=e.width/e.height,t.aspectRatio>e.aspectRatio?e.aspectWidth=e.height*t.aspectRatio:e.aspectHeight=e.width/t.aspectRatio),t._width=t.width||Math.ceil(e.aspectWidth||e.width),t._height=t.height||Math.ceil(e.aspectHeight||e.height);}t.width||(t._x=t.x||0,t._x+=e.x-Math.round(e.aspectWidth?Math.abs(e.aspectWidth-e.width)/2:0)),t.height||(t._y=t.y||0,t._y+=e.y-Math.round(e.aspectHeight?Math.abs(e.aspectHeight-e.height)/2:0));}function A(t,e){let r=d(e,true),o=a(r),n=t.color||"#333333",s=t.height||("number"==typeof t._height?t._height:0)||32,h=t.width||("number"==typeof t._width?t._width:0)||32,l,p=t.id,c;if(!p&&(this.idCounter=this.idCounter||0,p="highcharts-pattern-"+this.idCounter+"-"+(this.chartIndex||0),++this.idCounter),this.forExport&&(p+="-export"),this.defIds=this.defIds||[],this.defIds.indexOf(p)>-1)return;this.defIds.push(p);let f={id:p,patternUnits:"userSpaceOnUse",patternContentUnits:t.patternContentUnits||"userSpaceOnUse",width:h,height:s,x:t._x||t.x||0,y:t._y||t.y||0};t._inverted&&(f.patternTransform="scale(1, -1)",t.patternTransform&&(t.patternTransform+=" scale(1, -1)")),t.patternTransform&&(f.patternTransform=t.patternTransform);let g=this.createElement("pattern").attr(f).add(this.defs);if(g.id=p,t.path){if(c=i.isObject(t.path)?t.path:{d:t.path},t.backgroundColor){var m;m=t.backgroundColor,this.rect(0,0,h,s).attr({fill:m}).add(g);}l={d:c.d},this.styledMode||(l.stroke=c.stroke||n,l["stroke-width"]=d(c.strokeWidth,2),l.fill=c.fill||"none"),c.transform&&(l.transform=c.transform),this.createElement("path").attr(l).add(g),g.color=n;}else t.image&&(r?this.image(t.image,0,0,h,s,function(){this.animate({opacity:d(t.opacity,1)},o),u(this.element,"load");}).attr({opacity:0}).add(g):this.image(t.image,0,0,h,s).add(g));return t.image&&r||void 0===t.opacity||[].forEach.call(g.element.childNodes,e=>{e.setAttribute("opacity",t.opacity);}),this.patternElements=this.patternElements||{},this.patternElements[p]=g,g}function C(t){let e=this.options.color;e&&e.pattern&&!e.pattern.color?(delete this.options.color,t.apply(this,[].slice.call(arguments,1)),e.pattern.color=this.color,this.color=this.options.color=e):t.apply(this,[].slice.call(arguments,1));}function E(){if(!this.chart?.mapView)return;let t=this.chart,e=t.renderer,r=e.patternElements;e.defIds?.length&&r&&this.points.filter(function(t){return !!t.graphic&&(t.graphic.element.hasAttribute("fill")||t.graphic.element.hasAttribute("color")||t.graphic.element.hasAttribute("stroke"))&&!t.options.color?.pattern?.image&&!!t.group?.scaleX&&!!t.group?.scaleY}).map(function(t){let r=(t.graphic?.element.getAttribute("fill")||t.graphic?.element.getAttribute("color")||t.graphic?.element.getAttribute("stroke")||"").replace(e.url,"").replace("url(#","").replace(")","");return [r,{x:t.group?.scaleX||1,y:t.group?.scaleY||1}]}).filter(function([t,e],r,i){return ""!==t&&-1!==t.indexOf("highcharts-pattern-")&&!i.some(function([e,i],a){return e===t&&a<r})}).forEach(function([t,e]){r[t].scaleX=1/e.x,r[t].scaleY=1/e.y,r[t].updateTransform("patternTransform");});}return {compose:function t(e,r,i){let a=r.prototype.pointClass;f(n,t)&&(s(e,"endResize",x),s(e,"redraw",w),p(a.prototype,{calculatePatternDimensions:_}),s(a,"afterInit",M),s(r,"render",b),g(r.prototype,"getColor",C),s(r,"afterRender",E),s(r,"mapZoomComplete",E),p(i.prototype,{addPattern:A}),s(i,"complexColor",L));},patterns:m}}),r(e,"masters/modules/pattern-fill.src.js",[e["Core/Globals.js"],e["Extensions/PatternFill.js"]],function(t,e){t.patterns=e.patterns,e.compose(t.Chart,t.Series,t.SVGRenderer);});});
35
- } (patternFill));
36
- return patternFill.exports;
101
+ /**
102
+ * Check if the given value is *inter-element whitespace*.
103
+ *
104
+ * @param {Nodes | string} thing
105
+ * Thing to check (`Node` or `string`).
106
+ * @returns {boolean}
107
+ * Whether the `value` is inter-element whitespace (`boolean`): consisting of
108
+ * zero or more of space, tab (`\t`), line feed (`\n`), carriage return
109
+ * (`\r`), or form feed (`\f`); if a node is passed it must be a `Text` node,
110
+ * whose `value` field is checked.
111
+ */
112
+ function whitespace(thing) {
113
+ return typeof thing === 'object'
114
+ ? thing.type === 'text'
115
+ ? empty$1(thing.value)
116
+ : false
117
+ : empty$1(thing)
37
118
  }
38
119
 
39
- requirePatternFill();
120
+ /**
121
+ * @param {string} value
122
+ * @returns {boolean}
123
+ */
124
+ function empty$1(value) {
125
+ return value.replace(re, '') === ''
126
+ }
40
127
 
41
- const PieChart = ({
42
- data,
43
- width = 230,
44
- height = 180,
45
- size = '60%',
46
- colors = ['#2652a8', '#b47813', '#aa1a32']
47
- }) => {
48
- const noData = data.metrics.some(m => m.transparent);
49
- const options = useMemo(() => {
50
- const chartData = data.metrics.filter(metric => metric.transparent || metric.value > 0).map((metric, index) => ({
51
- name: metric.label,
52
- y: metric.value,
53
- color: metric.transparent ? checkerboardPattern() : colors[index % colors.length]
54
- }));
55
- return {
56
- chart: {
57
- type: 'pie',
58
- backgroundColor: 'transparent',
59
- width: width,
60
- height: height,
61
- style: {
62
- fontFamily: fontFamily$1
63
- }
64
- },
65
- title: {
66
- text: undefined
67
- },
68
- tooltip: {
69
- pointFormat: '<span><b>{point.y}</b> ({point.percentage:.1f}%)</span>',
70
- style: {
71
- fontFamily: fontFamily$1,
72
- fontSize: '13px'
73
- },
74
- useHTML: true
75
- },
76
- plotOptions: {
77
- pie: {
78
- size: size,
79
- allowPointSelect: true,
80
- cursor: 'pointer',
81
- dataLabels: {
82
- enabled: true,
83
- format: '{point.name}<br><b>{point.y}</b> ({point.percentage:.1f}%)',
84
- distance: 20,
85
- style: {
86
- fontSize: '13px',
87
- fontWeight: '100',
88
- textOutline: 'none',
89
- fontFamily: fontFamily$1
90
- },
91
- connectorColor: '#666',
92
- connectorWidth: 1,
93
- overflow: 'allow',
94
- crop: false
95
- },
96
- showInLegend: false
97
- }
98
- },
99
- series: [{
100
- type: 'pie',
101
- name: '',
102
- colorByPoint: true,
103
- data: chartData
104
- }],
105
- credits: {
106
- enabled: false
107
- },
108
- accessibility: {
109
- enabled: false
110
- }
111
- };
112
- }, [data, width, height, size, colors]);
113
- return /*#__PURE__*/React$1.createElement("div", {
114
- style: styles$7.chartWrapper
115
- }, /*#__PURE__*/React$1.createElement("div", {
116
- style: {
117
- ...styles$7.chartContainer,
118
- width,
119
- height,
120
- position: 'relative'
121
- }
122
- }, noData && /*#__PURE__*/React$1.createElement(CheckerboardBackground, {
123
- width: width,
124
- height: height
125
- }), /*#__PURE__*/React$1.createElement("div", {
126
- style: {
127
- position: 'relative',
128
- zIndex: 1
128
+ /**
129
+ * @import {Schema as SchemaType, Space} from 'property-information'
130
+ */
131
+
132
+ /** @type {SchemaType} */
133
+ class Schema {
134
+ /**
135
+ * @param {SchemaType['property']} property
136
+ * Property.
137
+ * @param {SchemaType['normal']} normal
138
+ * Normal.
139
+ * @param {Space | undefined} [space]
140
+ * Space.
141
+ * @returns
142
+ * Schema.
143
+ */
144
+ constructor(property, normal, space) {
145
+ this.normal = normal;
146
+ this.property = property;
147
+
148
+ if (space) {
149
+ this.space = space;
129
150
  }
130
- }, /*#__PURE__*/React$1.createElement(HighchartsReact, {
131
- highcharts: Highcharts$1,
132
- options: options
133
- }))), /*#__PURE__*/React$1.createElement("div", {
134
- style: styles$7.agentName
135
- }, data.name));
136
- };
137
- const fontFamily$1 = 'Pretendard, -apple-system, BlinkMacSystemFont, sans-serif';
138
- const styles$7 = {
139
- chartWrapper: {
140
- background: 'transparent',
141
- textAlign: 'center',
142
- display: 'flex',
143
- flexDirection: 'column',
144
- justifyContent: 'center',
145
- alignItems: 'center'
146
- },
147
- chartContainer: {
148
- display: 'flex',
149
- alignItems: 'center',
150
- justifyContent: 'center'
151
- },
152
- agentName: {
153
- fontSize: '12px',
154
- fontWeight: '100',
155
- marginTop: '-30px',
156
- color: '#333'
157
151
  }
158
- };
159
- const CheckerboardBackground = ({
160
- width,
161
- height
162
- }) => {
163
- const circleSize = Math.min(width, height) * 0.47;
164
- return /*#__PURE__*/React$1.createElement("div", {
165
- style: {
166
- position: 'absolute',
167
- width: circleSize,
168
- height: circleSize,
169
- borderRadius: '50%',
170
- backgroundImage: `
171
- linear-gradient(45deg, #e0e0e0 25%, transparent 25%),
172
- linear-gradient(-45deg, #e0e0e0 25%, transparent 25%),
173
- linear-gradient(45deg, transparent 75%, #e0e0e0 75%),
174
- linear-gradient(-45deg, transparent 75%, #e0e0e0 75%)
175
- `,
176
- backgroundSize: '10px 10px',
177
- backgroundPosition: '0 0, 0 5px, 5px -5px, -5px 0px',
178
- backgroundColor: '#ffffff',
179
- zIndex: 0
180
- }
181
- });
182
- };
183
- const checkerboardPattern = () => ({
184
- pattern: {
185
- path: {
186
- d: 'M 0 0 L 5 5 M 4.5 -0.5 L 5.5 0.5 M -0.5 4.5 L 0.5 5.5',
187
- stroke: '#d0d0d0',
188
- strokeWidth: 1
189
- },
190
- width: 5,
191
- height: 5,
192
- backgroundColor: '#ffffff',
193
- opacity: 1
194
- }
195
- });
152
+ }
196
153
 
197
- const ColumnChart = ({
198
- data,
199
- width,
200
- height = 230
201
- }) => {
202
- const series = useMemo(() => {
203
- return data.series.map((item, sindex) => ({
204
- ...item,
205
- data: item.data.map((value, index) => ({
206
- y: value,
207
- color: data.colors[index % data.colors.length] + alphas[sindex % alphas.length]
208
- }))
209
- }));
210
- }, [data]);
211
- const colors = useMemo(() => {
212
- return data.series.map((_, index) => data.colors[0] + alphas[index % alphas.length]);
213
- }, [data]);
214
- const options = useMemo(() => {
215
- return {
216
- chart: {
217
- type: 'column',
218
- backgroundColor: 'transparent',
219
- width: width,
220
- height: height,
221
- style: {
222
- fontFamily: fontFamily
223
- }
224
- },
225
- title: {
226
- text: undefined
227
- },
228
- tooltip: {
229
- pointFormat: '<span><b>{point.y}</b></span>',
230
- style: {
231
- fontFamily: fontFamily,
232
- fontSize: '13px',
233
- fontWeight: '100'
234
- },
235
- useHTML: true
236
- },
237
- plotOptions: {
238
- column: {
239
- //size: size
240
- }
241
- },
242
- xAxis: {
243
- categories: data.categories,
244
- crosshair: true,
245
- labels: {
246
- style: {
247
- color: '#777',
248
- fontFamily: fontFamily,
249
- fontWeight: '400'
250
- }
251
- },
252
- lineColor: '#aaa'
253
- },
254
- yAxis: {
255
- title: {
256
- text: undefined
257
- },
258
- labels: {
259
- style: {
260
- fontFamily: fontFamily,
261
- fontSize: '12px',
262
- fontWeight: '100'
263
- }
264
- },
265
- gridLineColor: '#f9f9f9'
266
- },
267
- legend: {
268
- layout: 'vertical',
269
- itemStyle: {
270
- fontFamily: fontFamily,
271
- fontSize: '12px',
272
- fontWeight: '100'
273
- },
274
- useHTML: true
275
- },
276
- series: series,
277
- colors: colors,
278
- credits: {
279
- enabled: false
280
- },
281
- accessibility: {
282
- enabled: false
283
- }
284
- };
285
- }, [data, width, height, series, colors]);
286
- return /*#__PURE__*/React$1.createElement("div", {
287
- style: styles$6.chartWrapper
288
- }, /*#__PURE__*/React$1.createElement(HighchartsReact, {
289
- highcharts: Highcharts$1,
290
- options: options
291
- }));
292
- };
293
- const fontFamily = 'Pretendard, -apple-system, BlinkMacSystemFont, sans-serif';
294
- const styles$6 = {
295
- chartWrapper: {
296
- background: 'transparent',
297
- textAlign: 'center',
298
- display: 'flex',
299
- flexDirection: 'column',
300
- justifyContent: 'center',
301
- alignItems: 'center'
154
+ Schema.prototype.normal = {};
155
+ Schema.prototype.property = {};
156
+ Schema.prototype.space = undefined;
157
+
158
+ /**
159
+ * @import {Info, Space} from 'property-information'
160
+ */
161
+
162
+
163
+ /**
164
+ * @param {ReadonlyArray<Schema>} definitions
165
+ * Definitions.
166
+ * @param {Space | undefined} [space]
167
+ * Space.
168
+ * @returns {Schema}
169
+ * Schema.
170
+ */
171
+ function merge(definitions, space) {
172
+ /** @type {Record<string, Info>} */
173
+ const property = {};
174
+ /** @type {Record<string, string>} */
175
+ const normal = {};
176
+
177
+ for (const definition of definitions) {
178
+ Object.assign(property, definition.property);
179
+ Object.assign(normal, definition.normal);
302
180
  }
303
- };
304
- const alphas = ['ff', 'bb', '77', '33'];
305
181
 
306
- function _extends() {
307
- return _extends = Object.assign ? Object.assign.bind() : function (n) {
308
- for (var e = 1; e < arguments.length; e++) {
309
- var t = arguments[e];
310
- for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
311
- }
312
- return n;
313
- }, _extends.apply(null, arguments);
182
+ return new Schema(property, normal, space)
314
183
  }
315
184
 
316
- function toValue(value) {
317
- return value && typeof value === 'object' ? value.value : value;
318
- }
319
- function toPercent(value) {
320
- return Math.round(value * 100 * 100) / 100;
321
- }
322
- function formatNumber(value) {
323
- return value !== undefined ? value.toLocaleString() : '-';
324
- }
325
- function formatToPercent(value) {
326
- return formatPercent(toPercent(value));
327
- }
328
- function formatPercent(value) {
329
- return value !== undefined ? `${value.toLocaleString()}%` : '-';
330
- }
331
- function formatDuration(value) {
332
- value = toValue(value);
333
- if (!value) return '-';
334
- let day = Math.floor(value / (60 * 60 * 24));
335
- let hour = Math.floor(value / (60 * 60)) - day * 24;
336
- let minute = Math.floor(value / 60) - (day * 24 + hour) * 60;
337
- let second = Math.round(value % 60);
338
- day = day > 0 ? `${day.toLocaleString()}일 ` : '';
339
- hour = hour > 0 ? `${hour >= 10 ? hour : '0' + hour}시간 ` : '';
340
- minute = `${minute >= 10 ? minute : '0' + minute}분 `;
341
- second = `${second >= 10 ? second : '0' + second}초`;
342
- return `${day}${hour}${minute}${second}`;
343
- }
344
- function formatBytes(value) {
345
- return value !== undefined ? `${value.toLocaleString()} bytes` : '-';
185
+ /**
186
+ * Get the cleaned case insensitive form of an attribute or property.
187
+ *
188
+ * @param {string} value
189
+ * An attribute-like or property-like name.
190
+ * @returns {string}
191
+ * Value that can be used to look up the properly cased property on a
192
+ * `Schema`.
193
+ */
194
+ function normalize$1(value) {
195
+ return value.toLowerCase()
346
196
  }
347
- function format(value, type) {
348
- switch (type) {
349
- case 'TO_PERCENT':
350
- return formatToPercent(value);
351
- case 'DURATION':
352
- return formatDuration(value);
353
- case 'BYTES':
354
- return formatBytes(value);
355
- case 'PERCENT':
356
- return formatPercent(value);
357
- default:
358
- return formatNumber(value);
197
+
198
+ /**
199
+ * @import {Info as InfoType} from 'property-information'
200
+ */
201
+
202
+ /** @type {InfoType} */
203
+ class Info {
204
+ /**
205
+ * @param {string} property
206
+ * Property.
207
+ * @param {string} attribute
208
+ * Attribute.
209
+ * @returns
210
+ * Info.
211
+ */
212
+ constructor(property, attribute) {
213
+ this.attribute = attribute;
214
+ this.property = property;
359
215
  }
360
216
  }
361
217
 
362
- const all$1 = [[blue[500]], [purple[500], '#4168a6', '#81a7e1'], [green[500], '#debb7f', '#ecdbbe'], [yellow[500], '#1b8286', '#4ab3b6'], [red[500]], [orange[500]], [lime[500]], ['#54AAF9'], ['#BB4ECD'], ['#6DDBBA'], ['#FFE81C'], ['#FA7EBA'], ['#F55713'], ['#51B304'], ['#1559B2'], ['#733FAB'], ['#1C7B5F'], ['#D87500'], ['#C91E48'], ['#2F862F']];
363
- [[blue[400], blue[500]], [purple[400], purple[500]], [green[400], green[500]], [yellow[400], yellow[500]], [red[400], red[500]], [orange[400], orange[500]], [lime[400], lime[500]]];
364
- [[alpha(blue[500], 0.2), 'transparent', blue[300]], [alpha(purple[500], 0.2), 'transparent', purple[500]], [alpha(green[500], 0.2), 'transparent', green[500]], [alpha(yellow[500], 0.2), 'transparent', yellow[500]], [alpha(red[500], 0.2), 'transparent', red[500]], [alpha(orange[500], 0.2), 'transparent', orange[500]], [alpha(lime[500], 0.2), 'transparent', lime[500]]];
365
- const preset = ['#003f5c', '#a05195', '#665191', '#2f4b7c', '#d45087', '#f95d6a', '#ff7c43', '#ffa600'];
366
- all$1.map(color => color[0]);
367
-
368
- highchartsAccessibility(Highcharts$1);
369
- highchartsAnnotations(Highcharts$1);
370
- function Chart(props) {
371
- const [legendLimitEnabled, setLegendLimitEnabled] = useState(props.legendLimit > 0);
372
- const [options, setOptions] = useState(toOptions(props, legendLimitEnabled));
373
- useEffect(() => {
374
- if (props.delay) setTimeout(() => setOptions(toOptions(props, legendLimitEnabled, handleLegendItemClick)), props.delay);else setOptions(toOptions(props, legendLimitEnabled, handleLegendItemClick));
375
- // eslint-disable-next-line
376
- }, [props]);
377
- const handleLegendItemClick = useCallback(() => setLegendLimitEnabled(false), []);
378
- return /*#__PURE__*/React.createElement(React.Fragment, null, options && /*#__PURE__*/React.createElement(HighchartsReact, {
379
- highcharts: Highcharts$1,
380
- options: options
381
- }));
382
- }
383
- function toOptions(props, legendLimitEnabled, handleLegendItemClick) {
384
- const {
385
- title = '',
386
- type,
387
- categorize,
388
- stacking,
389
- showLegend = true,
390
- showDataLabel,
391
- xAxisType,
392
- xAxisLabel = true,
393
- xAxisLabelFormat,
394
- xAxisTickInterval,
395
- yAxisLabelEnabled = true,
396
- yAxisLabelFormat,
397
- yAxisTickInterval = null,
398
- yAxisPlotLines = [],
399
- opacity = 1,
400
- innerSize = 0,
401
- colors: customColors,
402
- backgroundColor = undefined,
403
- xPlotIndex,
404
- dimension,
405
- metrics,
406
- records = [],
407
- metas,
408
- height = 200,
409
- legendLimit,
410
- legendAlign = 'center',
411
- tooltip = {},
412
- secondaryXAxis = []
413
- } = props;
414
- const {
415
- outside
416
- } = tooltip;
417
- const pie = type === 'pie';
418
- const centers = pieCenters(metrics.length);
419
- const size = pieSize(metrics.length);
420
- const colors = customColors ? customColors : preset;
421
- const categories = records.map(record => record[dimension]);
422
- const mainXAxis = records.map(r => r.time);
423
- const chartColorHandlers = {
424
- line: (colors, index) => ({
425
- color: colors[index],
426
- mainColor: colors[index]
427
- }),
428
- area: (colors, index) => ({
429
- color: colors[index][0],
430
- mainColor: colors[index][1]
431
- }),
432
- gradient: (colors, index) => ({
433
- color: {
434
- linearGradient: {
435
- x1: 0,
436
- y1: 0,
437
- x2: 0,
438
- y2: 1
439
- },
440
- stops: [[0, `${colors[index][0]}`], [0.95, `${colors[index][1]}`]]
441
- },
442
- mainColor: colors[index][2]
443
- })
444
- };
445
- const series = metrics.map(({
446
- chartType,
447
- metric
448
- }, index) => {
449
- const type = chartType === 'gradient' ? 'area' : chartType;
450
- const {
451
- color,
452
- mainColor
453
- } = chartColorHandlers[chartType](colors, index);
454
- const meta = metas[metric];
455
- let option = {
456
- type: type,
457
- name: meta ? meta.name : '',
458
- data: records.map(record => {
459
- const data = record.metric[metric] ?? null;
460
- return pie ? {
461
- name: record[dimension],
462
- y: data
463
- } : data;
464
- }),
465
- custom: {
466
- type: meta ? meta.type : '',
467
- pointerNames: meta?.pointerNames ?? null
468
- },
469
- center: centers[index] || [null, null],
470
- size: size,
471
- point: {
472
- events: {
473
- render: function () {
474
- this.graphic.attr({
475
- zIndex: this.y === 0 ? -1 : ZIndex.COMPARE_CHART_BASE - index
476
- });
477
- }
478
- }
479
- },
480
- showInLegend: pie && index > 0 ? false : true,
481
- color: color,
482
- lineColor: mainColor,
483
- lineWidth: 2,
484
- marker: {
485
- fillColor: mainColor
486
- },
487
- metric: metric
488
- };
489
- if (legendLimitEnabled) option = {
490
- ...option,
491
- visible: index < legendLimit
492
- };
493
- return option;
494
- });
495
- const yPlotLines = yAxisPlotLines.map((line, index) => {
496
- return {
497
- value: line.value,
498
- width: 1,
499
- color: line.color,
500
- dashStyle: "Dash",
501
- zIndex: ZIndex.AVERAGE_LINE_BASE + index,
502
- label: {
503
- text: line.label,
504
- align: line.labelAlign,
505
- style: {
506
- color: line.labelColor,
507
- opacity: 0.7,
508
- fontSize: "12px",
509
- padding: '1px 5px'
510
- },
511
- y: -8,
512
- useHTML: true
513
- }
514
- };
515
- });
516
- const xPlotBands = [{
517
- from: xPlotIndex,
518
- to: categories.length - 1,
519
- color: 'rgba(0, 0, 0, 0.03)',
520
- zIndex: ZIndex.NOW_BAND
521
- }];
522
- const xPlotLines = [{
523
- color: "#aaa",
524
- width: 1,
525
- value: xPlotIndex,
526
- zIndex: ZIndex.NOW_BORDER,
527
- label: {
528
- text: "현재",
529
- rotation: 0,
530
- x: 5,
531
- y: 13,
532
- style: {
533
- fontWeight: 500,
534
- lineHeight: "16.8px",
535
- color: "#333",
536
- fontSize: "12px"
537
- }
538
- }
539
- }];
540
- return {
541
- chart: {
542
- type: type.toLowerCase(),
543
- height: height,
544
- backgroundColor,
545
- events: {
546
- render: secondaryXAxis.length === 0 ? undefined : function () {
547
- const chart = this;
548
- const visibleSeries = chart.series.filter(s => s.visible);
549
- let newCategories = null;
550
- if (visibleSeries.length === 1 && visibleSeries[0].options.metric === 'prev') {
551
- newCategories = secondaryXAxis;
552
- } else {
553
- newCategories = mainXAxis;
554
- }
555
- const isSame = JSON.stringify(chart.xAxis[0].categories) === JSON.stringify(newCategories);
556
- if (!isSame) {
557
- chart.xAxis[0].setCategories(newCategories);
558
- }
559
- }
560
- }
561
- },
562
- title: {
563
- text: ''
564
- },
565
- subtitle: {
566
- text: title
567
- },
568
- colors: colors,
569
- xAxis: {
570
- type: xAxisType,
571
- labels: {
572
- enabled: xAxisLabel,
573
- autoRotation: false,
574
- format: xAxisLabelFormat ? `{value:${xAxisLabelFormat}}` : undefined,
575
- style: {
576
- color: grey[600]
577
- }
578
- },
579
- categories: categorize ? categories : undefined,
580
- tickWidth: 1,
581
- tickInterval: xAxisTickInterval ?? (xAxisType === 'datetime' ? records.length / 20 : 1),
582
- lineColor: grey[900],
583
- tickColor: grey[900],
584
- crosshair: true,
585
- startOnTick: true,
586
- plotBands: xPlotIndex !== undefined ? xPlotBands : undefined,
587
- plotLines: xPlotIndex !== undefined ? xPlotLines : undefined
588
- },
589
- yAxis: {
590
- title: {
591
- text: ''
592
- },
593
- labels: {
594
- enabled: yAxisLabelEnabled,
595
- formatter: yAxisLabelFormat,
596
- style: {
597
- color: grey[600]
598
- }
599
- },
600
- tickInterval: yAxisTickInterval,
601
- gridLineColor: '#f8f8f8',
602
- plotLines: yPlotLines
603
- },
604
- plotOptions: {
605
- series: {
606
- opacity: opacity,
607
- stacking: stackingType(stacking),
608
- showInLegend: showLegend,
609
- dataLabels: {
610
- enabled: showDataLabel
611
- },
612
- colorByPoint: pie,
613
- lineWidth: 2,
614
- marker: {
615
- enabled: false,
616
- symbol: 'circle'
617
- },
618
- cursor: 'pointer',
619
- point: {
620
- events: {}
621
- },
622
- events: {
623
- legendItemClick: handleLegendItemClick
624
- }
625
- },
626
- pie: {
627
- allowPointSelect: true,
628
- innerSize: `${innerSize}%`
629
- }
630
- },
631
- legend: {
632
- align: legendAlign,
633
- verticalAlign: 'top',
634
- enabled: showLegend
635
- },
636
- tooltip: {
637
- followPointer: false,
638
- shared: true,
639
- shadow: false,
640
- useHTML: true,
641
- formatter: function () {
642
- return tooltipFormatter(this, tooltip);
643
- },
644
- outside: outside,
645
- style: {
646
- zIndex: 2000
647
- }
648
- },
649
- series: series,
650
- time: {
651
- useUTC: false,
652
- getTimezoneOffset: function () {
653
- return new Date().getTimezoneOffset();
654
- }
655
- },
656
- credits: {
657
- enabled: false
658
- }
659
- };
660
- }
661
- const tooltipFormatter = (_this, props) => {
662
- const {
663
- headerVisible = true,
664
- dateFormat,
665
- headerTime,
666
- legendColors = []
667
- } = props;
668
- let tooltip = '<div style="font-size: 14px;padding: 12px; min-width: 200px;">';
669
- if (headerVisible) {
670
- const xDate = new Date(_this.x);
671
- const date = formatDate(xDate, dateFormat);
672
- tooltip += `<div style="display: flex; justify-content: space-between; font-weight: bold; font-size: 12px;">
673
- <span style="font-size: 12px; color: #333;">${date}</span>`;
674
- if (headerTime) {
675
- const time = formatDate(xDate, '%H:%M');
676
- tooltip += `<span style="font-size: 12px; color: #333;">${time}</span>`;
677
- }
678
- tooltip += '</div>';
679
- }
680
- _this.points.forEach(point => {
681
- const type = point.series.options.custom.type;
682
- const value = type !== 'TO_PERCENT' ? format(point.y, type) : formatToPercent(_this.percentage / 100);
683
- const name = point.series.name;
684
- let color = type !== 'TO_PERCENT' ? point.series.color : point.color;
685
- if (legendColors.length !== 0) {
686
- color = legendColors[point.series.index];
687
- }
688
- tooltip += `<div style="display: flex; flex-direction: column; gap: 8px;">
689
- <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 15px;">
690
- <span style="width: 10px; height: 10px; border-radius: 2px; margin-right: 8px; background-color: ${color}"></span>
691
- <span style="flex-grow: 1; font-size: 14px; padding-right: 20px;">${name}</span>
692
- <span style="font-weight: bold; font-size: 14px;">${value}</span>
693
- </div>
694
- </div>`;
695
- });
696
- tooltip += '</div>';
697
- return tooltip;
698
- };
699
- function formatDate(data, format) {
700
- return Highcharts$1.dateFormat(format, data.getTime() - data.getTimezoneOffset() * 60000);
701
- }
702
- const ZIndex = {
703
- AVERAGE_LINE_BASE: 10,
704
- COMPARE_CHART_BASE: 5,
705
- NOW_BORDER: 2,
706
- NOW_BAND: 1
707
- };
708
- function stackingType(stacking) {
709
- return stacking ? stacking.toLowerCase() : '';
710
- }
711
- function pieCenters(count) {
712
- switch (count) {
713
- case 2:
714
- return [['25%', '50%'], ['75%', '50%']];
715
- case 3:
716
- return [['25%', '25%'], ['75%', '25%'], ['50%', '75%']];
717
- case 4:
718
- return [['25%', '25%'], ['75%', '25%'], ['25%', '75%'], ['75%', '75%']];
719
- default:
720
- return [];
721
- }
722
- }
723
- function pieSize(count) {
724
- switch (count) {
725
- case 3:
726
- return '50%';
727
- case 4:
728
- return '25%';
729
- default:
730
- return null;
731
- }
732
- }
733
-
734
- function TrendChart({
735
- colorIndex = 0,
736
- legendColors,
737
- isDaily,
738
- isRealtime,
739
- ...props
740
- }) {
741
- const colors = useMemo(() => {
742
- return all$1[colorIndex % all$1.length];
743
- }, [colorIndex]);
744
- const tooltip = useMemo(() => ({
745
- dateFormat: isRealtime ? '%H:%M' : '%Y-%m-%d',
746
- headerTime: !isDaily && !isRealtime,
747
- outside: props.tooltipOutSide,
748
- legendColors
749
- }), [isRealtime, isDaily, props.tooltipOutSide, legendColors]);
750
- return /*#__PURE__*/React.createElement(Chart, _extends({
751
- type: "areaspline",
752
- categorize: true,
753
- xAxisType: "datetime",
754
- xAxisLabelFormat: isDaily ? '%m-%d' : '%H:%M',
755
- colors: colors,
756
- tooltip: tooltip
757
- }, props));
758
- }
759
-
760
- function StackedAreaTrendChart({
761
- metrics,
762
- records,
763
- isDaily = false,
764
- xPlotIndex,
765
- xAxisTickInterval,
766
- yAxisLabelEnabled = false,
767
- legendLimit = 3,
768
- colors = defaultColors,
769
- ...props
770
- }) {
771
- const _metrics = useMemo(() => {
772
- return metrics.map(m => ({
773
- metric: m.id,
774
- chartType: 'area'
775
- }));
776
- }, [metrics]);
777
- const metas = useMemo(() => {
778
- const result = {
779
- time: {
780
- name: "일시",
781
- type: "DATE"
782
- }
783
- };
784
- metrics.forEach(m => {
785
- result[m.id] = {
786
- name: m.name,
787
- type: "NUMBER"
788
- };
789
- });
790
- return result;
791
- }, [metrics]);
792
- return /*#__PURE__*/React.createElement(TrendChart, _extends({
793
- dimension: "time",
794
- stacking: "normal",
795
- metrics: _metrics,
796
- metas: metas,
797
- records: records,
798
- isRealtime: xPlotIndex !== undefined,
799
- isDaily: isDaily,
800
- xPlotIndex: xPlotIndex,
801
- xAxisTickInterval: xAxisTickInterval,
802
- yAxisLabelEnabled: yAxisLabelEnabled,
803
- legendLimit: legendLimit,
804
- colors: colors
805
- }, props));
806
- }
807
- const defaultColors = [["rgba(54,115,237,0.8)", "#3673ed"], ["rgba(149,77,241,0.8)", "#954df1"], ["#4dc391", "#20b476"], ["#fbba3d", "#faa90c"], ["#f2426d", "#ef1348"]];
808
-
809
- function ok$1() {}
810
-
811
- function unreachable() {}
812
-
813
- /**
814
- * @typedef Options
815
- * Configuration for `stringify`.
816
- * @property {boolean} [padLeft=true]
817
- * Whether to pad a space before a token.
818
- * @property {boolean} [padRight=false]
819
- * Whether to pad a space after a token.
820
- */
821
-
822
-
823
- /**
824
- * Serialize an array of strings or numbers to comma-separated tokens.
825
- *
826
- * @param {Array<string|number>} values
827
- * List of tokens.
828
- * @param {Options} [options]
829
- * Configuration for `stringify` (optional).
830
- * @returns {string}
831
- * Comma-separated tokens.
832
- */
833
- function stringify$1(values, options) {
834
- const settings = {};
835
-
836
- // Ensure the last empty entry is seen.
837
- const input = values[values.length - 1] === '' ? [...values, ''] : values;
838
-
839
- return input
840
- .join(
841
- (settings.padRight ? ' ' : '') +
842
- ',' +
843
- (settings.padLeft === false ? '' : ' ')
844
- )
845
- .trim()
846
- }
847
-
848
- /**
849
- * @typedef Options
850
- * Configuration.
851
- * @property {boolean | null | undefined} [jsx=false]
852
- * Support JSX identifiers (default: `false`).
853
- */
854
-
855
- const nameRe = /^[$_\p{ID_Start}][$_\u{200C}\u{200D}\p{ID_Continue}]*$/u;
856
- const nameReJsx = /^[$_\p{ID_Start}][-$_\u{200C}\u{200D}\p{ID_Continue}]*$/u;
857
-
858
- /** @type {Options} */
859
- const emptyOptions$2 = {};
860
-
861
- /**
862
- * Checks if the given value is a valid identifier name.
863
- *
864
- * @param {string} name
865
- * Identifier to check.
866
- * @param {Options | null | undefined} [options]
867
- * Configuration (optional).
868
- * @returns {boolean}
869
- * Whether `name` can be an identifier.
870
- */
871
- function name(name, options) {
872
- const settings = emptyOptions$2;
873
- const re = settings.jsx ? nameReJsx : nameRe;
874
- return re.test(name)
875
- }
876
-
877
- /**
878
- * @typedef {import('hast').Nodes} Nodes
879
- */
880
-
881
- // HTML whitespace expression.
882
- // See <https://infra.spec.whatwg.org/#ascii-whitespace>.
883
- const re = /[ \t\n\f\r]/g;
884
-
885
- /**
886
- * Check if the given value is *inter-element whitespace*.
887
- *
888
- * @param {Nodes | string} thing
889
- * Thing to check (`Node` or `string`).
890
- * @returns {boolean}
891
- * Whether the `value` is inter-element whitespace (`boolean`): consisting of
892
- * zero or more of space, tab (`\t`), line feed (`\n`), carriage return
893
- * (`\r`), or form feed (`\f`); if a node is passed it must be a `Text` node,
894
- * whose `value` field is checked.
895
- */
896
- function whitespace(thing) {
897
- return typeof thing === 'object'
898
- ? thing.type === 'text'
899
- ? empty$1(thing.value)
900
- : false
901
- : empty$1(thing)
902
- }
903
-
904
- /**
905
- * @param {string} value
906
- * @returns {boolean}
907
- */
908
- function empty$1(value) {
909
- return value.replace(re, '') === ''
910
- }
911
-
912
- /**
913
- * @import {Schema as SchemaType, Space} from 'property-information'
914
- */
915
-
916
- /** @type {SchemaType} */
917
- class Schema {
918
- /**
919
- * @param {SchemaType['property']} property
920
- * Property.
921
- * @param {SchemaType['normal']} normal
922
- * Normal.
923
- * @param {Space | undefined} [space]
924
- * Space.
925
- * @returns
926
- * Schema.
927
- */
928
- constructor(property, normal, space) {
929
- this.normal = normal;
930
- this.property = property;
931
-
932
- if (space) {
933
- this.space = space;
934
- }
935
- }
936
- }
937
-
938
- Schema.prototype.normal = {};
939
- Schema.prototype.property = {};
940
- Schema.prototype.space = undefined;
941
-
942
- /**
943
- * @import {Info, Space} from 'property-information'
944
- */
945
-
946
-
947
- /**
948
- * @param {ReadonlyArray<Schema>} definitions
949
- * Definitions.
950
- * @param {Space | undefined} [space]
951
- * Space.
952
- * @returns {Schema}
953
- * Schema.
954
- */
955
- function merge(definitions, space) {
956
- /** @type {Record<string, Info>} */
957
- const property = {};
958
- /** @type {Record<string, string>} */
959
- const normal = {};
960
-
961
- for (const definition of definitions) {
962
- Object.assign(property, definition.property);
963
- Object.assign(normal, definition.normal);
964
- }
965
-
966
- return new Schema(property, normal, space)
967
- }
968
-
969
- /**
970
- * Get the cleaned case insensitive form of an attribute or property.
971
- *
972
- * @param {string} value
973
- * An attribute-like or property-like name.
974
- * @returns {string}
975
- * Value that can be used to look up the properly cased property on a
976
- * `Schema`.
977
- */
978
- function normalize$1(value) {
979
- return value.toLowerCase()
980
- }
981
-
982
- /**
983
- * @import {Info as InfoType} from 'property-information'
984
- */
985
-
986
- /** @type {InfoType} */
987
- class Info {
988
- /**
989
- * @param {string} property
990
- * Property.
991
- * @param {string} attribute
992
- * Attribute.
993
- * @returns
994
- * Info.
995
- */
996
- constructor(property, attribute) {
997
- this.attribute = attribute;
998
- this.property = property;
999
- }
1000
- }
1001
-
1002
- Info.prototype.attribute = '';
1003
- Info.prototype.booleanish = false;
1004
- Info.prototype.boolean = false;
1005
- Info.prototype.commaOrSpaceSeparated = false;
1006
- Info.prototype.commaSeparated = false;
1007
- Info.prototype.defined = false;
1008
- Info.prototype.mustUseProperty = false;
1009
- Info.prototype.number = false;
1010
- Info.prototype.overloadedBoolean = false;
1011
- Info.prototype.property = '';
1012
- Info.prototype.spaceSeparated = false;
1013
- Info.prototype.space = undefined;
218
+ Info.prototype.attribute = '';
219
+ Info.prototype.booleanish = false;
220
+ Info.prototype.boolean = false;
221
+ Info.prototype.commaOrSpaceSeparated = false;
222
+ Info.prototype.commaSeparated = false;
223
+ Info.prototype.defined = false;
224
+ Info.prototype.mustUseProperty = false;
225
+ Info.prototype.number = false;
226
+ Info.prototype.overloadedBoolean = false;
227
+ Info.prototype.property = '';
228
+ Info.prototype.spaceSeparated = false;
229
+ Info.prototype.space = undefined;
1014
230
 
1015
231
  let powers = 0;
1016
232
 
@@ -1027,14 +243,14 @@ function increment() {
1027
243
  }
1028
244
 
1029
245
  var types = /*#__PURE__*/Object.freeze({
1030
- __proto__: null,
1031
- boolean: boolean,
1032
- booleanish: booleanish,
1033
- commaOrSpaceSeparated: commaOrSpaceSeparated,
1034
- commaSeparated: commaSeparated,
1035
- number: number,
1036
- overloadedBoolean: overloadedBoolean,
1037
- spaceSeparated: spaceSeparated
246
+ __proto__: null,
247
+ boolean: boolean,
248
+ booleanish: booleanish,
249
+ commaOrSpaceSeparated: commaOrSpaceSeparated,
250
+ commaSeparated: commaSeparated,
251
+ number: number,
252
+ overloadedBoolean: overloadedBoolean,
253
+ spaceSeparated: spaceSeparated
1038
254
  });
1039
255
 
1040
256
  /**
@@ -2274,6 +1490,10 @@ function stringify(values) {
2274
1490
  return values.join(' ').trim()
2275
1491
  }
2276
1492
 
1493
+ function getDefaultExportFromCjs (x) {
1494
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
1495
+ }
1496
+
2277
1497
  var cjs$2 = {};
2278
1498
 
2279
1499
  var cjs$1;
@@ -4038,12 +3258,12 @@ function one(value, includeImageAlt, includeHtml) {
4038
3258
  }
4039
3259
 
4040
3260
  if ('children' in value) {
4041
- return all(value.children, includeImageAlt, includeHtml)
3261
+ return all$1(value.children, includeImageAlt, includeHtml)
4042
3262
  }
4043
3263
  }
4044
3264
 
4045
3265
  if (Array.isArray(value)) {
4046
- return all(value, includeImageAlt, includeHtml)
3266
+ return all$1(value, includeImageAlt, includeHtml)
4047
3267
  }
4048
3268
 
4049
3269
  return ''
@@ -4061,7 +3281,7 @@ function one(value, includeImageAlt, includeHtml) {
4061
3281
  * @returns {string}
4062
3282
  * Serialized nodes.
4063
3283
  */
4064
- function all(values, includeImageAlt, includeHtml) {
3284
+ function all$1(values, includeImageAlt, includeHtml) {
4065
3285
  /** @type {Array<string>} */
4066
3286
  const result = [];
4067
3287
  let index = -1;
@@ -14013,16 +13233,16 @@ const disable = {
14013
13233
  };
14014
13234
 
14015
13235
  var defaultConstructs = /*#__PURE__*/Object.freeze({
14016
- __proto__: null,
14017
- attentionMarkers: attentionMarkers,
14018
- contentInitial: contentInitial,
14019
- disable: disable,
14020
- document: document$1,
14021
- flow: flow,
14022
- flowInitial: flowInitial,
14023
- insideSpan: insideSpan,
14024
- string: string,
14025
- text: text$1
13236
+ __proto__: null,
13237
+ attentionMarkers: attentionMarkers,
13238
+ contentInitial: contentInitial,
13239
+ disable: disable,
13240
+ document: document$1,
13241
+ flow: flow,
13242
+ flowInitial: flowInitial,
13243
+ insideSpan: insideSpan,
13244
+ string: string,
13245
+ text: text$1
14026
13246
  });
14027
13247
 
14028
13248
  /**
@@ -21463,7 +20683,7 @@ function ToolContextProvider({
21463
20683
  const kinds = useMemo(() => message.kinds ?? [], [message]);
21464
20684
  const tools = useMemo(() => message.content.filter(c => c.type === 'tool'), [message]);
21465
20685
  const configMap = useMemo(() => makeTaskConfigs(tools), [tools]);
21466
- return /*#__PURE__*/React.createElement(ToolContext.Provider, {
20686
+ return /*#__PURE__*/React$1.createElement(ToolContext.Provider, {
21467
20687
  value: {
21468
20688
  kinds: kinds,
21469
20689
  tools,
@@ -21584,69 +20804,178 @@ const isToday = (from, to) => {
21584
20804
  const date = new Date(now.toLocaleString('en-US', {
21585
20805
  timeZone: 'Asia/Seoul'
21586
20806
  }));
21587
- const today = date.getFullYear() + String(date.getMonth() + 1).padStart(2, '0') + String(date.getDate()).padStart(2, '0');
21588
- return from === today && to === today;
21589
- };
21590
- const isOneDay = (from, to) => {
21591
- return from === to;
21592
- };
21593
- const formatDateRange = (from, to) => {
21594
- const fromDate = dayjs(from, 'YYYYMMDD');
21595
- const toDate = dayjs(to, 'YYYYMMDD');
21596
- const today = dayjs().startOf('day');
21597
- if (from === to) return formatSingleDate(fromDate, today);
21598
- return formatRange(fromDate, toDate, today);
21599
- };
21600
- const formatSingleDate = (date, today) => {
21601
- const diffDays = today.diff(date, 'day');
21602
- if (diffDays === 0) return '오늘';
21603
- if (diffDays === 1) return '어제';
21604
- if (diffDays === 2) return '그제';
21605
- return date.format('YYYY년 M월 D일');
20807
+ const today = date.getFullYear() + String(date.getMonth() + 1).padStart(2, '0') + String(date.getDate()).padStart(2, '0');
20808
+ return from === today && to === today;
20809
+ };
20810
+ const isOneDay = (from, to) => {
20811
+ return from === to;
20812
+ };
20813
+ const formatDateRange = (from, to) => {
20814
+ const fromDate = dayjs(from, 'YYYYMMDD');
20815
+ const toDate = dayjs(to, 'YYYYMMDD');
20816
+ const today = dayjs().startOf('day');
20817
+ if (from === to) return formatSingleDate(fromDate, today);
20818
+ return formatRange(fromDate, toDate, today);
20819
+ };
20820
+ const formatSingleDate = (date, today) => {
20821
+ const diffDays = today.diff(date, 'day');
20822
+ if (diffDays === 0) return '오늘';
20823
+ if (diffDays === 1) return '어제';
20824
+ if (diffDays === 2) return '그제';
20825
+ return date.format('YYYY년 M월 D일');
20826
+ };
20827
+ const formatRange = (fromDate, toDate, today) => {
20828
+ const thisWeekStart = today.startOf('week'); // 일요일
20829
+ const thisWeekEnd = today.endOf('week'); // 토요일
20830
+
20831
+ if (fromDate.isSame(thisWeekStart, 'day') && (toDate.isSame(today, 'day') || toDate.isSame(thisWeekEnd, 'day'))) {
20832
+ return '이번주';
20833
+ }
20834
+ const lastWeekStart = today.subtract(1, 'week').startOf('week');
20835
+ const lastWeekEnd = today.subtract(1, 'week').endOf('week');
20836
+ if (fromDate.isSame(lastWeekStart, 'day') && toDate.isSame(lastWeekEnd, 'day')) {
20837
+ return '지난주';
20838
+ }
20839
+ const twoWeeksAgoStart = today.subtract(2, 'week').startOf('week');
20840
+ const twoWeeksAgoEnd = today.subtract(2, 'week').endOf('week');
20841
+ if (fromDate.isSame(twoWeeksAgoStart, 'day') && toDate.isSame(twoWeeksAgoEnd, 'day')) {
20842
+ return '지지난주';
20843
+ }
20844
+ const thisMonthStart = today.startOf('month');
20845
+ const thisMonthEnd = today.endOf('month');
20846
+ if (fromDate.isSame(thisMonthStart, 'day') && (toDate.isSame(today, 'day') || toDate.isSame(thisMonthEnd, 'day'))) {
20847
+ return '이번달';
20848
+ }
20849
+ const lastMonthStart = today.subtract(1, 'month').startOf('month');
20850
+ const lastMonthEnd = today.subtract(1, 'month').endOf('month');
20851
+ if (fromDate.isSame(lastMonthStart, 'day') && toDate.isSame(lastMonthEnd, 'day')) {
20852
+ return '지난달';
20853
+ }
20854
+ const twoMonthsAgoStart = today.subtract(2, 'month').startOf('month');
20855
+ const twoMonthsAgoEnd = today.subtract(2, 'month').endOf('month');
20856
+ if (fromDate.isSame(twoMonthsAgoStart, 'day') && toDate.isSame(twoMonthsAgoEnd, 'day')) {
20857
+ return '지지난달';
20858
+ }
20859
+ const fromFormatted = formatDateInRange(fromDate, today);
20860
+ const toFormatted = formatDateInRange(toDate, today);
20861
+ return `${fromFormatted} ~ ${toFormatted}`;
20862
+ };
20863
+ const formatDateInRange = (date, today) => {
20864
+ const diffDays = today.diff(date, 'day');
20865
+ if (diffDays === 0) return '오늘';
20866
+ if (diffDays === 1) return '어제';
20867
+ if (diffDays === 2) return '그제';
20868
+ return date.format('YYYY년 M월 D일');
20869
+ };
20870
+
20871
+ const ColumnChart = ({
20872
+ data,
20873
+ width,
20874
+ height = 230
20875
+ }) => {
20876
+ const series = useMemo(() => {
20877
+ return data.series.map((item, sindex) => ({
20878
+ ...item,
20879
+ data: item.data.map((value, index) => ({
20880
+ y: value,
20881
+ color: data.colors[index % data.colors.length] + alphas[sindex % alphas.length]
20882
+ }))
20883
+ }));
20884
+ }, [data]);
20885
+ const colors = useMemo(() => {
20886
+ return data.series.map((_, index) => data.colors[0] + alphas[index % alphas.length]);
20887
+ }, [data]);
20888
+ const options = useMemo(() => {
20889
+ return {
20890
+ chart: {
20891
+ type: 'column',
20892
+ backgroundColor: 'transparent',
20893
+ width: width,
20894
+ height: height,
20895
+ style: {
20896
+ fontFamily: fontFamily$1
20897
+ }
20898
+ },
20899
+ title: {
20900
+ text: undefined
20901
+ },
20902
+ tooltip: {
20903
+ pointFormat: '<span><b>{point.y}</b></span>',
20904
+ style: {
20905
+ fontFamily: fontFamily$1,
20906
+ fontSize: '13px',
20907
+ fontWeight: '100'
20908
+ },
20909
+ useHTML: true
20910
+ },
20911
+ plotOptions: {
20912
+ column: {
20913
+ //size: size
20914
+ }
20915
+ },
20916
+ xAxis: {
20917
+ categories: data.categories,
20918
+ crosshair: true,
20919
+ labels: {
20920
+ style: {
20921
+ color: '#777',
20922
+ fontFamily: fontFamily$1,
20923
+ fontWeight: '400'
20924
+ }
20925
+ },
20926
+ lineColor: '#aaa'
20927
+ },
20928
+ yAxis: {
20929
+ title: {
20930
+ text: undefined
20931
+ },
20932
+ labels: {
20933
+ style: {
20934
+ fontFamily: fontFamily$1,
20935
+ fontSize: '12px',
20936
+ fontWeight: '100'
20937
+ }
20938
+ },
20939
+ gridLineColor: '#f9f9f9'
20940
+ },
20941
+ legend: {
20942
+ layout: 'vertical',
20943
+ itemStyle: {
20944
+ fontFamily: fontFamily$1,
20945
+ fontSize: '12px',
20946
+ fontWeight: '100'
20947
+ },
20948
+ useHTML: true
20949
+ },
20950
+ series: series,
20951
+ colors: colors,
20952
+ credits: {
20953
+ enabled: false
20954
+ },
20955
+ accessibility: {
20956
+ enabled: false
20957
+ }
20958
+ };
20959
+ }, [data, width, height, series, colors]);
20960
+ return /*#__PURE__*/React$1.createElement("div", {
20961
+ style: styles$7.chartWrapper
20962
+ }, /*#__PURE__*/React$1.createElement(HighchartsReact, {
20963
+ highcharts: Highcharts,
20964
+ options: options
20965
+ }));
21606
20966
  };
21607
- const formatRange = (fromDate, toDate, today) => {
21608
- const thisWeekStart = today.startOf('week'); // 일요일
21609
- const thisWeekEnd = today.endOf('week'); // 토요일
21610
-
21611
- if (fromDate.isSame(thisWeekStart, 'day') && (toDate.isSame(today, 'day') || toDate.isSame(thisWeekEnd, 'day'))) {
21612
- return '이번주';
21613
- }
21614
- const lastWeekStart = today.subtract(1, 'week').startOf('week');
21615
- const lastWeekEnd = today.subtract(1, 'week').endOf('week');
21616
- if (fromDate.isSame(lastWeekStart, 'day') && toDate.isSame(lastWeekEnd, 'day')) {
21617
- return '지난주';
21618
- }
21619
- const twoWeeksAgoStart = today.subtract(2, 'week').startOf('week');
21620
- const twoWeeksAgoEnd = today.subtract(2, 'week').endOf('week');
21621
- if (fromDate.isSame(twoWeeksAgoStart, 'day') && toDate.isSame(twoWeeksAgoEnd, 'day')) {
21622
- return '지지난주';
21623
- }
21624
- const thisMonthStart = today.startOf('month');
21625
- const thisMonthEnd = today.endOf('month');
21626
- if (fromDate.isSame(thisMonthStart, 'day') && (toDate.isSame(today, 'day') || toDate.isSame(thisMonthEnd, 'day'))) {
21627
- return '이번달';
21628
- }
21629
- const lastMonthStart = today.subtract(1, 'month').startOf('month');
21630
- const lastMonthEnd = today.subtract(1, 'month').endOf('month');
21631
- if (fromDate.isSame(lastMonthStart, 'day') && toDate.isSame(lastMonthEnd, 'day')) {
21632
- return '지난달';
21633
- }
21634
- const twoMonthsAgoStart = today.subtract(2, 'month').startOf('month');
21635
- const twoMonthsAgoEnd = today.subtract(2, 'month').endOf('month');
21636
- if (fromDate.isSame(twoMonthsAgoStart, 'day') && toDate.isSame(twoMonthsAgoEnd, 'day')) {
21637
- return '지지난달';
20967
+ const fontFamily$1 = 'Pretendard, -apple-system, BlinkMacSystemFont, sans-serif';
20968
+ const styles$7 = {
20969
+ chartWrapper: {
20970
+ background: 'transparent',
20971
+ textAlign: 'center',
20972
+ display: 'flex',
20973
+ flexDirection: 'column',
20974
+ justifyContent: 'center',
20975
+ alignItems: 'center'
21638
20976
  }
21639
- const fromFormatted = formatDateInRange(fromDate, today);
21640
- const toFormatted = formatDateInRange(toDate, today);
21641
- return `${fromFormatted} ~ ${toFormatted}`;
21642
- };
21643
- const formatDateInRange = (date, today) => {
21644
- const diffDays = today.diff(date, 'day');
21645
- if (diffDays === 0) return '오늘';
21646
- if (diffDays === 1) return '어제';
21647
- if (diffDays === 2) return '그제';
21648
- return date.format('YYYY년 M월 D일');
21649
20977
  };
20978
+ const alphas = ['ff', 'bb', '77', '33'];
21650
20979
 
21651
20980
  const ColumnChartContent = ({
21652
20981
  tools = []
@@ -21677,33 +21006,536 @@ function toData$1(tools, configMap) {
21677
21006
  name: `<b>${configMap.get(taskId)}</b> <span style="font-size:10px">(${formatDateRange(from, to)})</span>`,
21678
21007
  data: []
21679
21008
  };
21680
- const result = reduce(content.result.result);
21681
- item.data.push(result.input);
21682
- item.data.push(result.output);
21683
- if (hasConvert) item.data.push(result.filter);
21684
- item.data.push(result.error);
21685
- items.push(item);
21009
+ const result = reduce(content.result.result);
21010
+ item.data.push(result.input);
21011
+ item.data.push(result.output);
21012
+ if (hasConvert) item.data.push(result.filter);
21013
+ item.data.push(result.error);
21014
+ items.push(item);
21015
+ });
21016
+ return {
21017
+ colors: hasConvert ? ['#333333', '#2652a8', '#b47813', '#aa1a32'] : ['#333333', '#2652a8', '#aa1a32'],
21018
+ categories: hasConvert ? ['입력', '처리', '필터', '에러'] : ['입력', '처리', '에러'],
21019
+ series: items
21020
+ };
21021
+ }
21022
+ function reduce(data) {
21023
+ return data.reduce((acc, item) => {
21024
+ acc.input += item.metric.input;
21025
+ acc.output += item.metric.output;
21026
+ acc.filter += item.metric.filter;
21027
+ acc.error += item.metric.error;
21028
+ return acc;
21029
+ }, {
21030
+ input: 0,
21031
+ output: 0,
21032
+ filter: 0,
21033
+ error: 0
21034
+ });
21035
+ }
21036
+
21037
+ function _extends() {
21038
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
21039
+ for (var e = 1; e < arguments.length; e++) {
21040
+ var t = arguments[e];
21041
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
21042
+ }
21043
+ return n;
21044
+ }, _extends.apply(null, arguments);
21045
+ }
21046
+
21047
+ function toValue(value) {
21048
+ return value && typeof value === 'object' ? value.value : value;
21049
+ }
21050
+ function toPercent(value) {
21051
+ return Math.round(value * 100 * 100) / 100;
21052
+ }
21053
+ function formatNumber(value) {
21054
+ return value !== undefined ? value.toLocaleString() : '-';
21055
+ }
21056
+ function formatToPercent(value) {
21057
+ return formatPercent(toPercent(value));
21058
+ }
21059
+ function formatPercent(value) {
21060
+ return value !== undefined ? `${value.toLocaleString()}%` : '-';
21061
+ }
21062
+ function formatDuration(value) {
21063
+ value = toValue(value);
21064
+ if (!value) return '-';
21065
+ let day = Math.floor(value / (60 * 60 * 24));
21066
+ let hour = Math.floor(value / (60 * 60)) - day * 24;
21067
+ let minute = Math.floor(value / 60) - (day * 24 + hour) * 60;
21068
+ let second = Math.round(value % 60);
21069
+ day = day > 0 ? `${day.toLocaleString()}일 ` : '';
21070
+ hour = hour > 0 ? `${hour >= 10 ? hour : '0' + hour}시간 ` : '';
21071
+ minute = `${minute >= 10 ? minute : '0' + minute}분 `;
21072
+ second = `${second >= 10 ? second : '0' + second}초`;
21073
+ return `${day}${hour}${minute}${second}`;
21074
+ }
21075
+ function formatBytes(value) {
21076
+ return value !== undefined ? `${value.toLocaleString()} bytes` : '-';
21077
+ }
21078
+ function format(value, type) {
21079
+ switch (type) {
21080
+ case 'TO_PERCENT':
21081
+ return formatToPercent(value);
21082
+ case 'DURATION':
21083
+ return formatDuration(value);
21084
+ case 'BYTES':
21085
+ return formatBytes(value);
21086
+ case 'PERCENT':
21087
+ return formatPercent(value);
21088
+ default:
21089
+ return formatNumber(value);
21090
+ }
21091
+ }
21092
+
21093
+ const all = [[blue[500]], [purple[500], '#4168a6', '#81a7e1'], [green[500], '#debb7f', '#ecdbbe'], [yellow[500], '#1b8286', '#4ab3b6'], [red[500]], [orange[500]], [lime[500]], ['#54AAF9'], ['#BB4ECD'], ['#6DDBBA'], ['#FFE81C'], ['#FA7EBA'], ['#F55713'], ['#51B304'], ['#1559B2'], ['#733FAB'], ['#1C7B5F'], ['#D87500'], ['#C91E48'], ['#2F862F']];
21094
+ [[blue[400], blue[500]], [purple[400], purple[500]], [green[400], green[500]], [yellow[400], yellow[500]], [red[400], red[500]], [orange[400], orange[500]], [lime[400], lime[500]]];
21095
+ [[alpha(blue[500], 0.2), 'transparent', blue[300]], [alpha(purple[500], 0.2), 'transparent', purple[500]], [alpha(green[500], 0.2), 'transparent', green[500]], [alpha(yellow[500], 0.2), 'transparent', yellow[500]], [alpha(red[500], 0.2), 'transparent', red[500]], [alpha(orange[500], 0.2), 'transparent', orange[500]], [alpha(lime[500], 0.2), 'transparent', lime[500]]];
21096
+ const preset = ['#003f5c', '#a05195', '#665191', '#2f4b7c', '#d45087', '#f95d6a', '#ff7c43', '#ffa600'];
21097
+ all.map(color => color[0]);
21098
+
21099
+ highchartsAccessibility(Highcharts);
21100
+ highchartsAnnotations(Highcharts);
21101
+ function Chart(props) {
21102
+ const [legendLimitEnabled, setLegendLimitEnabled] = useState(props.legendLimit > 0);
21103
+ const [options, setOptions] = useState(toOptions(props, legendLimitEnabled));
21104
+ useEffect(() => {
21105
+ if (props.delay) setTimeout(() => setOptions(toOptions(props, legendLimitEnabled, handleLegendItemClick)), props.delay);else setOptions(toOptions(props, legendLimitEnabled, handleLegendItemClick));
21106
+ // eslint-disable-next-line
21107
+ }, [props]);
21108
+ const handleLegendItemClick = useCallback(() => setLegendLimitEnabled(false), []);
21109
+ return /*#__PURE__*/React$1.createElement(React$1.Fragment, null, options && /*#__PURE__*/React$1.createElement(HighchartsReact, {
21110
+ highcharts: Highcharts,
21111
+ options: options
21112
+ }));
21113
+ }
21114
+ function toOptions(props, legendLimitEnabled, handleLegendItemClick) {
21115
+ const {
21116
+ title = '',
21117
+ type,
21118
+ categorize,
21119
+ stacking,
21120
+ showLegend = true,
21121
+ showDataLabel,
21122
+ xAxisType,
21123
+ xAxisLabel = true,
21124
+ xAxisLabelFormat,
21125
+ xAxisTickInterval,
21126
+ yAxisLabelEnabled = true,
21127
+ yAxisLabelFormat,
21128
+ yAxisTickInterval = null,
21129
+ yAxisPlotLines = [],
21130
+ opacity = 1,
21131
+ innerSize = 0,
21132
+ colors: customColors,
21133
+ backgroundColor = undefined,
21134
+ xPlotIndex,
21135
+ dimension,
21136
+ metrics,
21137
+ records = [],
21138
+ metas,
21139
+ height = 200,
21140
+ legendLimit,
21141
+ legendAlign = 'center',
21142
+ tooltip = {},
21143
+ secondaryXAxis = []
21144
+ } = props;
21145
+ const {
21146
+ outside
21147
+ } = tooltip;
21148
+ const pie = type === 'pie';
21149
+ const centers = pieCenters(metrics.length);
21150
+ const size = pieSize(metrics.length);
21151
+ const colors = customColors ? customColors : preset;
21152
+ const categories = records.map(record => record[dimension]);
21153
+ const mainXAxis = records.map(r => r.time);
21154
+ const chartColorHandlers = {
21155
+ line: (colors, index) => ({
21156
+ color: colors[index],
21157
+ mainColor: colors[index]
21158
+ }),
21159
+ area: (colors, index) => ({
21160
+ color: colors[index][0],
21161
+ mainColor: colors[index][1]
21162
+ }),
21163
+ gradient: (colors, index) => ({
21164
+ color: {
21165
+ linearGradient: {
21166
+ x1: 0,
21167
+ y1: 0,
21168
+ x2: 0,
21169
+ y2: 1
21170
+ },
21171
+ stops: [[0, `${colors[index][0]}`], [0.95, `${colors[index][1]}`]]
21172
+ },
21173
+ mainColor: colors[index][2]
21174
+ })
21175
+ };
21176
+ const series = metrics.map(({
21177
+ chartType,
21178
+ metric
21179
+ }, index) => {
21180
+ const type = chartType === 'gradient' ? 'area' : chartType;
21181
+ const {
21182
+ color,
21183
+ mainColor
21184
+ } = chartColorHandlers[chartType](colors, index);
21185
+ const meta = metas[metric];
21186
+ let option = {
21187
+ type: type,
21188
+ name: meta ? meta.name : '',
21189
+ data: records.map(record => {
21190
+ const data = record.metric[metric] ?? null;
21191
+ return pie ? {
21192
+ name: record[dimension],
21193
+ y: data
21194
+ } : data;
21195
+ }),
21196
+ custom: {
21197
+ type: meta ? meta.type : '',
21198
+ pointerNames: meta?.pointerNames ?? null
21199
+ },
21200
+ center: centers[index] || [null, null],
21201
+ size: size,
21202
+ point: {
21203
+ events: {
21204
+ render: function () {
21205
+ this.graphic.attr({
21206
+ zIndex: this.y === 0 ? -1 : ZIndex.COMPARE_CHART_BASE - index
21207
+ });
21208
+ }
21209
+ }
21210
+ },
21211
+ showInLegend: pie && index > 0 ? false : true,
21212
+ color: color,
21213
+ lineColor: mainColor,
21214
+ lineWidth: 2,
21215
+ marker: {
21216
+ fillColor: mainColor
21217
+ },
21218
+ metric: metric
21219
+ };
21220
+ if (legendLimitEnabled) option = {
21221
+ ...option,
21222
+ visible: index < legendLimit
21223
+ };
21224
+ return option;
21686
21225
  });
21226
+ const yPlotLines = yAxisPlotLines.map((line, index) => {
21227
+ return {
21228
+ value: line.value,
21229
+ width: 1,
21230
+ color: line.color,
21231
+ dashStyle: "Dash",
21232
+ zIndex: ZIndex.AVERAGE_LINE_BASE + index,
21233
+ label: {
21234
+ text: line.label,
21235
+ align: line.labelAlign,
21236
+ style: {
21237
+ color: line.labelColor,
21238
+ opacity: 0.7,
21239
+ fontSize: "12px",
21240
+ padding: '1px 5px'
21241
+ },
21242
+ y: -8,
21243
+ useHTML: true
21244
+ }
21245
+ };
21246
+ });
21247
+ const xPlotBands = [{
21248
+ from: xPlotIndex,
21249
+ to: categories.length - 1,
21250
+ color: 'rgba(0, 0, 0, 0.03)',
21251
+ zIndex: ZIndex.NOW_BAND
21252
+ }];
21253
+ const xPlotLines = [{
21254
+ color: "#aaa",
21255
+ width: 1,
21256
+ value: xPlotIndex,
21257
+ zIndex: ZIndex.NOW_BORDER,
21258
+ label: {
21259
+ text: "현재",
21260
+ rotation: 0,
21261
+ x: 5,
21262
+ y: 13,
21263
+ style: {
21264
+ fontWeight: 500,
21265
+ lineHeight: "16.8px",
21266
+ color: "#333",
21267
+ fontSize: "12px"
21268
+ }
21269
+ }
21270
+ }];
21687
21271
  return {
21688
- colors: hasConvert ? ['#333333', '#2652a8', '#b47813', '#aa1a32'] : ['#333333', '#2652a8', '#aa1a32'],
21689
- categories: hasConvert ? ['입력', '처리', '필터', '에러'] : ['입력', '처리', '에러'],
21690
- series: items
21272
+ chart: {
21273
+ type: type.toLowerCase(),
21274
+ height: height,
21275
+ backgroundColor,
21276
+ events: {
21277
+ render: secondaryXAxis.length === 0 ? undefined : function () {
21278
+ const chart = this;
21279
+ const visibleSeries = chart.series.filter(s => s.visible);
21280
+ let newCategories = null;
21281
+ if (visibleSeries.length === 1 && visibleSeries[0].options.metric === 'prev') {
21282
+ newCategories = secondaryXAxis;
21283
+ } else {
21284
+ newCategories = mainXAxis;
21285
+ }
21286
+ const isSame = JSON.stringify(chart.xAxis[0].categories) === JSON.stringify(newCategories);
21287
+ if (!isSame) {
21288
+ chart.xAxis[0].setCategories(newCategories);
21289
+ }
21290
+ }
21291
+ }
21292
+ },
21293
+ title: {
21294
+ text: ''
21295
+ },
21296
+ subtitle: {
21297
+ text: title
21298
+ },
21299
+ colors: colors,
21300
+ xAxis: {
21301
+ type: xAxisType,
21302
+ labels: {
21303
+ enabled: xAxisLabel,
21304
+ autoRotation: false,
21305
+ format: xAxisLabelFormat ? `{value:${xAxisLabelFormat}}` : undefined,
21306
+ style: {
21307
+ color: grey[600]
21308
+ }
21309
+ },
21310
+ categories: categorize ? categories : undefined,
21311
+ tickWidth: 1,
21312
+ tickInterval: xAxisTickInterval ?? (xAxisType === 'datetime' ? records.length / 20 : 1),
21313
+ lineColor: grey[900],
21314
+ tickColor: grey[900],
21315
+ crosshair: true,
21316
+ startOnTick: true,
21317
+ plotBands: xPlotIndex !== undefined ? xPlotBands : undefined,
21318
+ plotLines: xPlotIndex !== undefined ? xPlotLines : undefined
21319
+ },
21320
+ yAxis: {
21321
+ title: {
21322
+ text: ''
21323
+ },
21324
+ labels: {
21325
+ enabled: yAxisLabelEnabled,
21326
+ formatter: yAxisLabelFormat,
21327
+ style: {
21328
+ color: grey[600]
21329
+ }
21330
+ },
21331
+ tickInterval: yAxisTickInterval,
21332
+ gridLineColor: '#f8f8f8',
21333
+ plotLines: yPlotLines
21334
+ },
21335
+ plotOptions: {
21336
+ series: {
21337
+ opacity: opacity,
21338
+ stacking: stackingType(stacking),
21339
+ showInLegend: showLegend,
21340
+ dataLabels: {
21341
+ enabled: showDataLabel
21342
+ },
21343
+ colorByPoint: pie,
21344
+ lineWidth: 2,
21345
+ marker: {
21346
+ enabled: false,
21347
+ symbol: 'circle'
21348
+ },
21349
+ cursor: 'pointer',
21350
+ point: {
21351
+ events: {}
21352
+ },
21353
+ events: {
21354
+ legendItemClick: handleLegendItemClick
21355
+ }
21356
+ },
21357
+ pie: {
21358
+ allowPointSelect: true,
21359
+ innerSize: `${innerSize}%`
21360
+ }
21361
+ },
21362
+ legend: {
21363
+ align: legendAlign,
21364
+ verticalAlign: 'top',
21365
+ enabled: showLegend
21366
+ },
21367
+ tooltip: {
21368
+ followPointer: false,
21369
+ shared: true,
21370
+ shadow: false,
21371
+ useHTML: true,
21372
+ formatter: function () {
21373
+ return tooltipFormatter(this, tooltip);
21374
+ },
21375
+ outside: outside,
21376
+ style: {
21377
+ zIndex: 2000
21378
+ }
21379
+ },
21380
+ series: series,
21381
+ time: {
21382
+ useUTC: false,
21383
+ getTimezoneOffset: function () {
21384
+ return new Date().getTimezoneOffset();
21385
+ }
21386
+ },
21387
+ credits: {
21388
+ enabled: false
21389
+ }
21691
21390
  };
21692
21391
  }
21693
- function reduce(data) {
21694
- return data.reduce((acc, item) => {
21695
- acc.input += item.metric.input;
21696
- acc.output += item.metric.output;
21697
- acc.filter += item.metric.filter;
21698
- acc.error += item.metric.error;
21699
- return acc;
21700
- }, {
21701
- input: 0,
21702
- output: 0,
21703
- filter: 0,
21704
- error: 0
21705
- });
21392
+ const tooltipFormatter = (_this, props) => {
21393
+ const {
21394
+ headerVisible = true,
21395
+ dateFormat,
21396
+ headerTime,
21397
+ legendColors = []
21398
+ } = props;
21399
+ let tooltip = '<div style="font-size: 14px;padding: 12px; min-width: 200px;">';
21400
+ if (headerVisible) {
21401
+ const xDate = new Date(_this.x);
21402
+ const date = formatDate(xDate, dateFormat);
21403
+ tooltip += `<div style="display: flex; justify-content: space-between; font-weight: bold; font-size: 12px;">
21404
+ <span style="font-size: 12px; color: #333;">${date}</span>`;
21405
+ if (headerTime) {
21406
+ const time = formatDate(xDate, '%H:%M');
21407
+ tooltip += `<span style="font-size: 12px; color: #333;">${time}</span>`;
21408
+ }
21409
+ tooltip += '</div>';
21410
+ }
21411
+ _this.points.forEach(point => {
21412
+ const type = point.series.options.custom.type;
21413
+ const value = type !== 'TO_PERCENT' ? format(point.y, type) : formatToPercent(_this.percentage / 100);
21414
+ const name = point.series.name;
21415
+ let color = type !== 'TO_PERCENT' ? point.series.color : point.color;
21416
+ if (legendColors.length !== 0) {
21417
+ color = legendColors[point.series.index];
21418
+ }
21419
+ tooltip += `<div style="display: flex; flex-direction: column; gap: 8px;">
21420
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-top: 15px;">
21421
+ <span style="width: 10px; height: 10px; border-radius: 2px; margin-right: 8px; background-color: ${color}"></span>
21422
+ <span style="flex-grow: 1; font-size: 14px; padding-right: 20px;">${name}</span>
21423
+ <span style="font-weight: bold; font-size: 14px;">${value}</span>
21424
+ </div>
21425
+ </div>`;
21426
+ });
21427
+ tooltip += '</div>';
21428
+ return tooltip;
21429
+ };
21430
+ function formatDate(data, format) {
21431
+ return Highcharts.dateFormat(format, data.getTime() - data.getTimezoneOffset() * 60000);
21432
+ }
21433
+ const ZIndex = {
21434
+ AVERAGE_LINE_BASE: 10,
21435
+ COMPARE_CHART_BASE: 5,
21436
+ NOW_BORDER: 2,
21437
+ NOW_BAND: 1
21438
+ };
21439
+ function stackingType(stacking) {
21440
+ return stacking ? stacking.toLowerCase() : '';
21441
+ }
21442
+ function pieCenters(count) {
21443
+ switch (count) {
21444
+ case 2:
21445
+ return [['25%', '50%'], ['75%', '50%']];
21446
+ case 3:
21447
+ return [['25%', '25%'], ['75%', '25%'], ['50%', '75%']];
21448
+ case 4:
21449
+ return [['25%', '25%'], ['75%', '25%'], ['25%', '75%'], ['75%', '75%']];
21450
+ default:
21451
+ return [];
21452
+ }
21453
+ }
21454
+ function pieSize(count) {
21455
+ switch (count) {
21456
+ case 3:
21457
+ return '50%';
21458
+ case 4:
21459
+ return '25%';
21460
+ default:
21461
+ return null;
21462
+ }
21463
+ }
21464
+
21465
+ function TrendChart({
21466
+ colorIndex = 0,
21467
+ legendColors,
21468
+ isDaily,
21469
+ isRealtime,
21470
+ ...props
21471
+ }) {
21472
+ const colors = useMemo(() => {
21473
+ return all[colorIndex % all.length];
21474
+ }, [colorIndex]);
21475
+ const tooltip = useMemo(() => ({
21476
+ dateFormat: isRealtime ? '%H:%M' : '%Y-%m-%d',
21477
+ headerTime: !isDaily && !isRealtime,
21478
+ outside: props.tooltipOutSide,
21479
+ legendColors
21480
+ }), [isRealtime, isDaily, props.tooltipOutSide, legendColors]);
21481
+ return /*#__PURE__*/React$1.createElement(Chart, _extends({
21482
+ type: "areaspline",
21483
+ categorize: true,
21484
+ xAxisType: "datetime",
21485
+ xAxisLabelFormat: isDaily ? '%m-%d' : '%H:%M',
21486
+ colors: colors,
21487
+ tooltip: tooltip
21488
+ }, props));
21489
+ }
21490
+
21491
+ function StackedAreaTrendChart({
21492
+ metrics,
21493
+ records,
21494
+ isDaily = false,
21495
+ xPlotIndex,
21496
+ xAxisTickInterval,
21497
+ yAxisLabelEnabled = false,
21498
+ legendLimit = 3,
21499
+ colors = defaultColors,
21500
+ ...props
21501
+ }) {
21502
+ const _metrics = useMemo(() => {
21503
+ return metrics.map(m => ({
21504
+ metric: m.id,
21505
+ chartType: 'area'
21506
+ }));
21507
+ }, [metrics]);
21508
+ const metas = useMemo(() => {
21509
+ const result = {
21510
+ time: {
21511
+ name: "일시",
21512
+ type: "DATE"
21513
+ }
21514
+ };
21515
+ metrics.forEach(m => {
21516
+ result[m.id] = {
21517
+ name: m.name,
21518
+ type: "NUMBER"
21519
+ };
21520
+ });
21521
+ return result;
21522
+ }, [metrics]);
21523
+ return /*#__PURE__*/React$1.createElement(TrendChart, _extends({
21524
+ dimension: "time",
21525
+ stacking: "normal",
21526
+ metrics: _metrics,
21527
+ metas: metas,
21528
+ records: records,
21529
+ isRealtime: xPlotIndex !== undefined,
21530
+ isDaily: isDaily,
21531
+ xPlotIndex: xPlotIndex,
21532
+ xAxisTickInterval: xAxisTickInterval,
21533
+ yAxisLabelEnabled: yAxisLabelEnabled,
21534
+ legendLimit: legendLimit,
21535
+ colors: colors
21536
+ }, props));
21706
21537
  }
21538
+ const defaultColors = [["rgba(54,115,237,0.8)", "#3673ed"], ["rgba(149,77,241,0.8)", "#954df1"], ["#4dc391", "#20b476"], ["#fbba3d", "#faa90c"], ["#f2426d", "#ef1348"]];
21707
21539
 
21708
21540
  function StackedAreaChartContent({
21709
21541
  tools
@@ -21797,6 +21629,162 @@ function xPlotIndex(tools) {
21797
21629
  }
21798
21630
  }
21799
21631
 
21632
+ const PieChart = ({
21633
+ data,
21634
+ width = 230,
21635
+ height = 180,
21636
+ size = '60%',
21637
+ colors = ['#2652a8', '#b47813', '#aa1a32']
21638
+ }) => {
21639
+ const noData = data.metrics.some(m => m.transparent);
21640
+ const options = useMemo(() => {
21641
+ const chartData = data.metrics.filter(metric => metric.transparent || metric.value > 0).map((metric, index) => ({
21642
+ name: metric.label,
21643
+ y: metric.value,
21644
+ color: metric.transparent ? checkerboardPattern() : colors[index % colors.length]
21645
+ }));
21646
+ return {
21647
+ chart: {
21648
+ type: 'pie',
21649
+ backgroundColor: 'transparent',
21650
+ width: width,
21651
+ height: height,
21652
+ style: {
21653
+ fontFamily: fontFamily
21654
+ }
21655
+ },
21656
+ title: {
21657
+ text: undefined
21658
+ },
21659
+ tooltip: {
21660
+ pointFormat: '<span><b>{point.y}</b> ({point.percentage:.1f}%)</span>',
21661
+ style: {
21662
+ fontFamily: fontFamily,
21663
+ fontSize: '13px'
21664
+ },
21665
+ useHTML: true
21666
+ },
21667
+ plotOptions: {
21668
+ pie: {
21669
+ size: size,
21670
+ allowPointSelect: true,
21671
+ cursor: 'pointer',
21672
+ dataLabels: {
21673
+ enabled: true,
21674
+ format: '{point.name}<br><b>{point.y}</b> ({point.percentage:.1f}%)',
21675
+ distance: 20,
21676
+ style: {
21677
+ fontSize: '13px',
21678
+ fontWeight: '100',
21679
+ textOutline: 'none',
21680
+ fontFamily: fontFamily
21681
+ },
21682
+ connectorColor: '#666',
21683
+ connectorWidth: 1,
21684
+ overflow: 'allow',
21685
+ crop: false
21686
+ },
21687
+ showInLegend: false
21688
+ }
21689
+ },
21690
+ series: [{
21691
+ type: 'pie',
21692
+ name: '',
21693
+ colorByPoint: true,
21694
+ data: chartData
21695
+ }],
21696
+ credits: {
21697
+ enabled: false
21698
+ },
21699
+ accessibility: {
21700
+ enabled: false
21701
+ }
21702
+ };
21703
+ }, [data, width, height, size, colors]);
21704
+ return /*#__PURE__*/React$1.createElement("div", {
21705
+ style: styles$6.chartWrapper
21706
+ }, /*#__PURE__*/React$1.createElement("div", {
21707
+ style: {
21708
+ ...styles$6.chartContainer,
21709
+ width,
21710
+ height,
21711
+ position: 'relative'
21712
+ }
21713
+ }, noData && /*#__PURE__*/React$1.createElement(CheckerboardBackground, {
21714
+ width: width,
21715
+ height: height
21716
+ }), /*#__PURE__*/React$1.createElement("div", {
21717
+ style: {
21718
+ position: 'relative',
21719
+ zIndex: 1
21720
+ }
21721
+ }, /*#__PURE__*/React$1.createElement(HighchartsReact, {
21722
+ highcharts: Highcharts,
21723
+ options: options
21724
+ }))), /*#__PURE__*/React$1.createElement("div", {
21725
+ style: styles$6.agentName
21726
+ }, data.name));
21727
+ };
21728
+ const fontFamily = 'Pretendard, -apple-system, BlinkMacSystemFont, sans-serif';
21729
+ const styles$6 = {
21730
+ chartWrapper: {
21731
+ background: 'transparent',
21732
+ textAlign: 'center',
21733
+ display: 'flex',
21734
+ flexDirection: 'column',
21735
+ justifyContent: 'center',
21736
+ alignItems: 'center'
21737
+ },
21738
+ chartContainer: {
21739
+ display: 'flex',
21740
+ alignItems: 'center',
21741
+ justifyContent: 'center'
21742
+ },
21743
+ agentName: {
21744
+ fontSize: '12px',
21745
+ fontWeight: '100',
21746
+ marginTop: '-30px',
21747
+ color: '#333'
21748
+ }
21749
+ };
21750
+ const CheckerboardBackground = ({
21751
+ width,
21752
+ height
21753
+ }) => {
21754
+ const circleSize = Math.min(width, height) * 0.47;
21755
+ return /*#__PURE__*/React$1.createElement("div", {
21756
+ style: {
21757
+ position: 'absolute',
21758
+ width: circleSize,
21759
+ height: circleSize,
21760
+ borderRadius: '50%',
21761
+ backgroundImage: `
21762
+ linear-gradient(45deg, #e0e0e0 25%, transparent 25%),
21763
+ linear-gradient(-45deg, #e0e0e0 25%, transparent 25%),
21764
+ linear-gradient(45deg, transparent 75%, #e0e0e0 75%),
21765
+ linear-gradient(-45deg, transparent 75%, #e0e0e0 75%)
21766
+ `,
21767
+ backgroundSize: '10px 10px',
21768
+ backgroundPosition: '0 0, 0 5px, 5px -5px, -5px 0px',
21769
+ backgroundColor: '#ffffff',
21770
+ zIndex: 0
21771
+ }
21772
+ });
21773
+ };
21774
+ const checkerboardPattern = () => ({
21775
+ pattern: {
21776
+ path: {
21777
+ d: 'M 0 0 L 5 5 M 4.5 -0.5 L 5.5 0.5 M -0.5 4.5 L 0.5 5.5',
21778
+ stroke: '#d0d0d0',
21779
+ strokeWidth: 1
21780
+ },
21781
+ width: 5,
21782
+ height: 5,
21783
+ backgroundColor: '#ffffff',
21784
+ opacity: 1
21785
+ }
21786
+ });
21787
+
21800
21788
  const PieChartContent = ({
21801
21789
  tool
21802
21790
  }) => {
@@ -22196,18 +22184,11 @@ const styles$1 = {
22196
22184
  }
22197
22185
  };
22198
22186
 
22199
- let globalConfig = {
22200
- apiUrl: ''
22201
- };
22202
- function getConfig() {
22203
- return globalConfig;
22204
- }
22205
-
22206
22187
  const {
22207
22188
  apiUrl
22208
22189
  } = getConfig();
22209
22190
  const useChatApi = defaultMessages => {
22210
- const [messages, setMessages] = useState(defaultMessages ?? []);
22191
+ const [messages, setMessages] = useState(defaultMessages ? defaultMessages : []);
22211
22192
  const [inputValue, setInputValue] = useState('');
22212
22193
  const [isLoading, setIsLoading] = useState(false);
22213
22194
  const [conversationId, setConversationId] = useState(null);
@@ -22300,16 +22281,16 @@ function AiChat({
22300
22281
  chatContainerRef,
22301
22282
  sendMessage
22302
22283
  } = useChatApi(defaultMessages);
22303
- return /*#__PURE__*/React.createElement(Stack, {
22284
+ return /*#__PURE__*/React$1.createElement(Stack, {
22304
22285
  sx: {
22305
22286
  ...styles.container,
22306
22287
  ...sx
22307
22288
  }
22308
- }, /*#__PURE__*/React.createElement(ChatMessages, {
22289
+ }, /*#__PURE__*/React$1.createElement(ChatMessages, {
22309
22290
  messages: messages,
22310
22291
  isLoading: isLoading,
22311
22292
  chatContainerRef: chatContainerRef
22312
- }), /*#__PURE__*/React.createElement(ChatInput, {
22293
+ }), /*#__PURE__*/React$1.createElement(ChatInput, {
22313
22294
  inputValue: inputValue,
22314
22295
  setInputValue: setInputValue,
22315
22296
  onSend: sendMessage,
@@ -22327,4 +22308,4 @@ const styles = {
22327
22308
  }
22328
22309
  };
22329
22310
 
22330
- export { AiChat, ColumnChart, PieChart, StackedAreaTrendChart };
22311
+ export { AiChat, ColumnChart, PieChart, StackedAreaTrendChart, configure$1 as configure, getConfig };