UNPKG

17.2 kBJavaScriptView Raw
1import * as i0 from '@angular/core';
2import { Component, ChangeDetectionStrategy, Optional, Input, NgModule } from '@angular/core';
3import * as i2 from '@angular/common';
4import { CommonModule } from '@angular/common';
5import * as i3 from '@angular/material/tooltip';
6import { MatTooltipModule } from '@angular/material/tooltip';
7import * as i4 from '@angular/material/icon';
8import { MatIconModule } from '@angular/material/icon';
9import * as i1 from '@angular/cdk/bidi';
10import { trigger, state, style, AUTO_STYLE, transition, group, query, animateChild, animate } from '@angular/animations';
11
12/**
13 * const tdCollapseAnimation
14 *
15 * Parameter Options:
16 * * duration: Duration the animation will run in milliseconds. Defaults to 150 ms.
17 * * delay: Delay before the animation will run in milliseconds. Defaults to 0 ms.
18 * * easeOnClose: Animation accelerates and decelerates when closing. Defaults to ease-in.
19 * * easeOnOpen: Animation accelerates and decelerates when opening. Defaults to ease-out.
20 *
21 * Returns an [AnimationTriggerMetadata] object with boolean states for a collapse/expand animation.
22 *
23 * usage: [@tdCollapse]="{ value: true | false, params: { duration: 500 }}"
24 */
25const tdCollapseAnimation = trigger('tdCollapse', [
26 state('1', style({
27 height: '0',
28 overflow: 'hidden',
29 })),
30 state('0', style({
31 height: AUTO_STYLE,
32 overflow: AUTO_STYLE,
33 })),
34 transition('0 => 1', [
35 style({
36 overflow: 'hidden',
37 height: AUTO_STYLE,
38 }),
39 group([
40 query('@*', animateChild(), { optional: true }),
41 animate('{{ duration }}ms {{ delay }}ms {{ ease }}', style({
42 height: '0',
43 overflow: 'hidden',
44 })),
45 ]),
46 ], { params: { duration: 150, delay: '0', ease: 'ease-in' } }),
47 transition('1 => 0', [
48 style({
49 height: '0',
50 overflow: 'hidden',
51 }),
52 group([
53 query('@*', animateChild(), { optional: true }),
54 animate('{{ duration }}ms {{ delay }}ms {{ ease }}', style({
55 overflow: 'hidden',
56 height: AUTO_STYLE,
57 })),
58 ]),
59 ], { params: { duration: 150, delay: '0', ease: 'ease-out' } }),
60]);
61
62class TdJsonFormatterComponent {
63 _changeDetectorRef;
64 _dir;
65 /**
66 * Max length for property names. Any names bigger than this get trunctated.
67 */
68 static KEY_MAX_LENGTH = 30;
69 /**
70 * Max length for preview string. Any names bigger than this get trunctated.
71 */
72 static PREVIEW_STRING_MAX_LENGTH = 80;
73 /**
74 * Max tooltip preview elements.
75 */
76 static PREVIEW_LIMIT = 5;
77 _key;
78 _data;
79 _children;
80 _open = false;
81 _levelsOpen = 0;
82 /**
83 * levelsOpen?: number
84 * Levels opened by default when JS object is formatted and rendered.
85 */
86 set levelsOpen(levelsOpen) {
87 if (!Number.isInteger(levelsOpen)) {
88 throw new Error('[levelsOpen] needs to be an integer.');
89 }
90 this._levelsOpen = levelsOpen;
91 this._open = levelsOpen > 0;
92 }
93 get levelsOpen() {
94 return this._levelsOpen;
95 }
96 get open() {
97 return this._open;
98 }
99 /**
100 * key?: string
101 * Tag to be displayed next to formatted object.
102 */
103 set key(key) {
104 this._key = key;
105 }
106 get key() {
107 const elipsis = this._key && this._key.length > TdJsonFormatterComponent.KEY_MAX_LENGTH
108 ? '…'
109 : '';
110 return this._key
111 ? this._key.substring(0, TdJsonFormatterComponent.KEY_MAX_LENGTH) +
112 elipsis
113 : this._key ?? '';
114 }
115 /**
116 * data: any
117 * JS object to be formatted.
118 */
119 set data(data) {
120 this._data = data;
121 this.parseChildren();
122 }
123 get data() {
124 return this._data;
125 }
126 get children() {
127 return this._children ?? [];
128 }
129 get isRTL() {
130 if (this._dir) {
131 return this._dir.dir === 'rtl';
132 }
133 return false;
134 }
135 constructor(_changeDetectorRef, _dir) {
136 this._changeDetectorRef = _changeDetectorRef;
137 this._dir = _dir;
138 }
139 /**
140 * Refreshes json-formatter and rerenders [data]
141 */
142 refresh() {
143 this._changeDetectorRef.markForCheck();
144 }
145 /**
146 * Toggles collapse/expanded state of component.
147 */
148 toggle() {
149 this._open = !this._open;
150 }
151 isObject() {
152 return this.getType(this._data) === 'object';
153 }
154 isArray() {
155 return Array.isArray(this._data);
156 }
157 hasChildren() {
158 return (this._children && this._children.length > 0) ?? false;
159 }
160 /**
161 * Gets parsed value depending on value type.
162 */
163 getValue(value) {
164 const type = this.getType(value);
165 if (type === 'undefined' || type === 'null') {
166 return type;
167 }
168 else if (type === 'date') {
169 value = new Date(value).toString();
170 }
171 else if (type === 'string') {
172 value = '"' + value + '"';
173 }
174 else if (type === 'function') {
175 // Remove content of the function
176 return (value
177 .toString()
178 .replace(/[\r\n]/g, '')
179 .replace(/\{.*\}/, '') + '{…}');
180 }
181 else if (Array.isArray(value)) {
182 return this.getObjectName() + ' [' + value.length + ']';
183 }
184 return value;
185 }
186 /**
187 * Gets type of object.
188 * returns 'null' if object is null and 'date' if value is object and can be parsed to a date.
189 */
190 getType(object) {
191 if (typeof object === 'object') {
192 if (!object) {
193 return 'null';
194 }
195 if (Array.isArray(object)) {
196 return 'object';
197 }
198 const date = new Date(object);
199 if (Object.prototype.toString.call(date) === '[object Date]' &&
200 !Number.isNaN(date.getTime())) {
201 return 'date';
202 }
203 }
204 return typeof object;
205 }
206 /**
207 * Generates string representation depending if its an object or function.
208 * see: http://stackoverflow.com/a/332429
209 */
210 getObjectName() {
211 const object = this._data;
212 if (this.isObject() && !object.constructor) {
213 return 'Object';
214 }
215 const funcNameRegex = /function (.{1,})\(/;
216 const results = funcNameRegex.exec(object.constructor.toString());
217 if (results && results.length > 1) {
218 return results[1];
219 }
220 else {
221 return '';
222 }
223 }
224 /**
225 * Creates preview of nodes children to render in tooltip depending if its an array or an object.
226 */
227 getPreview() {
228 let previewData;
229 let startChar = '{ ';
230 let endChar = ' }';
231 if (this.isArray()) {
232 const previewArray = Object.entries(this._data).slice(0, TdJsonFormatterComponent.PREVIEW_LIMIT) ?? [];
233 previewData = previewArray.map((obj) => {
234 return this.getValue(obj);
235 });
236 startChar = '[';
237 endChar = ']';
238 }
239 else {
240 const previewKeys = this._children?.slice(0, TdJsonFormatterComponent.PREVIEW_LIMIT) ?? [];
241 previewData = previewKeys.map((key) => {
242 return key + ': ' + this.getValue(this._data[key] ?? undefined);
243 });
244 }
245 const previewString = previewData.join(', ');
246 const ellipsis = previewData.length >= TdJsonFormatterComponent.PREVIEW_LIMIT ||
247 previewString.length > TdJsonFormatterComponent.PREVIEW_STRING_MAX_LENGTH
248 ? '…'
249 : '';
250 return (startChar +
251 previewString.substring(0, TdJsonFormatterComponent.PREVIEW_STRING_MAX_LENGTH) +
252 ellipsis +
253 endChar);
254 }
255 parseChildren() {
256 if (this.isObject()) {
257 this._children = Object.keys(this._data ?? {});
258 }
259 }
260 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: TdJsonFormatterComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.Dir, optional: true }], target: i0.ɵɵFactoryTarget.Component });
261 static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.2", type: TdJsonFormatterComponent, selector: "td-json-formatter", inputs: { levelsOpen: "levelsOpen", key: "key", data: "data" }, ngImport: i0, template: "<div class=\"td-json-formatter-wrapper\">\n <a\n class=\"td-key\"\n [class.td-key-node]=\"hasChildren()\"\n [class.td-key-leaf]=\"!hasChildren()\"\n [tabIndex]=\"isObject() ? 0 : -1\"\n (keydown.enter)=\"toggle()\"\n (click)=\"toggle()\"\n >\n <mat-icon class=\"td-node-icon\" *ngIf=\"hasChildren()\">\n {{\n open\n ? 'keyboard_arrow_down'\n : isRTL\n ? 'keyboard_arrow_left'\n : 'keyboard_arrow_right'\n }}\n </mat-icon>\n <span *ngIf=\"key\" class=\"key\">{{ key }}:</span>\n <span class=\"value\">\n <span\n [class.td-empty]=\"!hasChildren()\"\n *ngIf=\"isObject()\"\n [matTooltip]=\"getPreview()\"\n matTooltipPosition=\"after\"\n >\n <span class=\"td-object-name\">{{ getObjectName() }}</span>\n <span class=\"td-array-length\" *ngIf=\"isArray()\"\n >[{{ data['length'] }}]</span\n >\n </span>\n <span *ngIf=\"!isObject()\" [class]=\"getType(data)\">{{\n getValue(data)\n }}</span>\n </span>\n </a>\n <div class=\"td-object-children\" [@tdCollapse]=\"!(hasChildren() && open)\">\n <ng-template let-key ngFor [ngForOf]=\"children\">\n <td-json-formatter\n [key]=\"key\"\n [data]=\"data[key]\"\n [levelsOpen]=\"levelsOpen - 1\"\n ></td-json-formatter>\n </ng-template>\n </div>\n</div>\n", styles: [":host{display:block}.td-json-formatter-wrapper{padding-top:2px;padding-bottom:2px}.td-json-formatter-wrapper .td-key{box-sizing:border-box;display:flex;flex-direction:row;align-items:flex-start;align-content:center;max-width:100%;justify-content:flex-start}.td-json-formatter-wrapper .td-key.td-key-node:hover{cursor:pointer}.td-json-formatter-wrapper .td-object-children.ng-animating{overflow:hidden}.td-json-formatter-wrapper .td-object-children .td-key,.td-json-formatter-wrapper .td-object-children .td-object-children{padding-left:24px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-key,::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-object-children{padding-right:24px;padding-left:0}.td-json-formatter-wrapper .td-object-children .td-key.td-key-leaf,.td-json-formatter-wrapper .td-object-children .td-object-children.td-key-leaf{padding-left:48px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-key.td-key-leaf,::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-object-children.td-key-leaf{padding-right:48px;padding-left:0}.td-json-formatter-wrapper .value{margin-left:5px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .value{padding-right:5px;padding-left:0}.td-json-formatter-wrapper .value .td-empty{opacity:.5;text-decoration:line-through}.td-json-formatter-wrapper .value .string,.td-json-formatter-wrapper .value .date{word-break:break-word}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: TdJsonFormatterComponent, selector: "td-json-formatter", inputs: ["levelsOpen", "key", "data"] }], animations: [tdCollapseAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
262}
263i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: TdJsonFormatterComponent, decorators: [{
264 type: Component,
265 args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'td-json-formatter', animations: [tdCollapseAnimation], template: "<div class=\"td-json-formatter-wrapper\">\n <a\n class=\"td-key\"\n [class.td-key-node]=\"hasChildren()\"\n [class.td-key-leaf]=\"!hasChildren()\"\n [tabIndex]=\"isObject() ? 0 : -1\"\n (keydown.enter)=\"toggle()\"\n (click)=\"toggle()\"\n >\n <mat-icon class=\"td-node-icon\" *ngIf=\"hasChildren()\">\n {{\n open\n ? 'keyboard_arrow_down'\n : isRTL\n ? 'keyboard_arrow_left'\n : 'keyboard_arrow_right'\n }}\n </mat-icon>\n <span *ngIf=\"key\" class=\"key\">{{ key }}:</span>\n <span class=\"value\">\n <span\n [class.td-empty]=\"!hasChildren()\"\n *ngIf=\"isObject()\"\n [matTooltip]=\"getPreview()\"\n matTooltipPosition=\"after\"\n >\n <span class=\"td-object-name\">{{ getObjectName() }}</span>\n <span class=\"td-array-length\" *ngIf=\"isArray()\"\n >[{{ data['length'] }}]</span\n >\n </span>\n <span *ngIf=\"!isObject()\" [class]=\"getType(data)\">{{\n getValue(data)\n }}</span>\n </span>\n </a>\n <div class=\"td-object-children\" [@tdCollapse]=\"!(hasChildren() && open)\">\n <ng-template let-key ngFor [ngForOf]=\"children\">\n <td-json-formatter\n [key]=\"key\"\n [data]=\"data[key]\"\n [levelsOpen]=\"levelsOpen - 1\"\n ></td-json-formatter>\n </ng-template>\n </div>\n</div>\n", styles: [":host{display:block}.td-json-formatter-wrapper{padding-top:2px;padding-bottom:2px}.td-json-formatter-wrapper .td-key{box-sizing:border-box;display:flex;flex-direction:row;align-items:flex-start;align-content:center;max-width:100%;justify-content:flex-start}.td-json-formatter-wrapper .td-key.td-key-node:hover{cursor:pointer}.td-json-formatter-wrapper .td-object-children.ng-animating{overflow:hidden}.td-json-formatter-wrapper .td-object-children .td-key,.td-json-formatter-wrapper .td-object-children .td-object-children{padding-left:24px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-key,::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-object-children{padding-right:24px;padding-left:0}.td-json-formatter-wrapper .td-object-children .td-key.td-key-leaf,.td-json-formatter-wrapper .td-object-children .td-object-children.td-key-leaf{padding-left:48px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-key.td-key-leaf,::ng-deep [dir=rtl] .td-json-formatter-wrapper .td-object-children .td-object-children.td-key-leaf{padding-right:48px;padding-left:0}.td-json-formatter-wrapper .value{margin-left:5px}::ng-deep [dir=rtl] .td-json-formatter-wrapper .value{padding-right:5px;padding-left:0}.td-json-formatter-wrapper .value .td-empty{opacity:.5;text-decoration:line-through}.td-json-formatter-wrapper .value .string,.td-json-formatter-wrapper .value .date{word-break:break-word}\n"] }]
266 }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }, { type: i1.Dir, decorators: [{
267 type: Optional
268 }] }], propDecorators: { levelsOpen: [{
269 type: Input
270 }], key: [{
271 type: Input
272 }], data: [{
273 type: Input
274 }] } });
275
276class CovalentJsonFormatterModule {
277 static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentJsonFormatterModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
278 static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "17.1.2", ngImport: i0, type: CovalentJsonFormatterModule, declarations: [TdJsonFormatterComponent], imports: [CommonModule, MatTooltipModule, MatIconModule], exports: [TdJsonFormatterComponent] });
279 static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentJsonFormatterModule, imports: [CommonModule, MatTooltipModule, MatIconModule] });
280}
281i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: CovalentJsonFormatterModule, decorators: [{
282 type: NgModule,
283 args: [{
284 imports: [CommonModule, MatTooltipModule, MatIconModule],
285 declarations: [TdJsonFormatterComponent],
286 exports: [TdJsonFormatterComponent],
287 }]
288 }] });
289
290/**
291 * Generated bundle index. Do not edit.
292 */
293
294export { CovalentJsonFormatterModule, TdJsonFormatterComponent };
295//# sourceMappingURL=covalent-core-json-formatter.mjs.map