@tacdaed/fragments 1.0.0-beta.3 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/ng-package.json +20 -0
- package/package.json +22 -29
- package/src/lib/components/accordion/accordion.component.html +103 -0
- package/src/lib/components/accordion/accordion.component.scss +382 -0
- package/src/lib/components/accordion/accordion.component.spec.ts +147 -0
- package/src/lib/components/accordion/accordion.component.ts +211 -0
- package/src/lib/components/accordion/accordion.type.ts +82 -0
- package/src/lib/components/breadcrumb/breadcrumb.component.html +43 -0
- package/src/lib/components/breadcrumb/breadcrumb.component.scss +112 -0
- package/src/lib/components/breadcrumb/breadcrumb.component.spec.ts +33 -0
- package/src/lib/components/breadcrumb/breadcrumb.component.ts +103 -0
- package/src/lib/components/breadcrumb/breadcrumb.interface.ts +7 -0
- package/src/lib/components/button/button.component.html +57 -0
- package/src/lib/components/button/button.component.scss +445 -0
- package/src/lib/components/button/button.component.spec.ts +99 -0
- package/src/lib/components/button/button.component.ts +143 -0
- package/src/lib/components/button/button.type.ts +7 -0
- package/src/lib/components/card/card.component.html +44 -0
- package/src/lib/components/card/card.component.scss +114 -0
- package/src/lib/components/card/card.component.spec.ts +65 -0
- package/src/lib/components/card/card.component.ts +21 -0
- package/src/lib/components/card/card.type.ts +3 -0
- package/src/lib/components/code-block/code-block.component.html +55 -0
- package/src/lib/components/code-block/code-block.component.scss +122 -0
- package/src/lib/components/code-block/code-block.component.spec.ts +81 -0
- package/src/lib/components/code-block/code-block.component.ts +302 -0
- package/src/lib/components/code-block/code-block.interface.ts +28 -0
- package/src/lib/components/code-block/code-block.type.ts +73 -0
- package/src/lib/components/decorative/sparkle-field/sparkle-field.component.html +14 -0
- package/src/lib/components/decorative/sparkle-field/sparkle-field.component.scss +20 -0
- package/src/lib/components/decorative/sparkle-field/sparkle-field.component.spec.ts +38 -0
- package/src/lib/components/decorative/sparkle-field/sparkle-field.component.ts +181 -0
- package/src/lib/components/input/input-base.ts +187 -0
- package/src/lib/components/input/input-calendar/input-calendar.component.html +76 -0
- package/src/lib/components/input/input-calendar/input-calendar.component.scss +179 -0
- package/src/lib/components/input/input-calendar/input-calendar.component.spec.ts +44 -0
- package/src/lib/components/input/input-calendar/input-calendar.component.ts +299 -0
- package/src/lib/components/input/input-checkbox/input-checkbox.component.html +37 -0
- package/src/lib/components/input/input-checkbox/input-checkbox.component.scss +128 -0
- package/src/lib/components/input/input-checkbox/input-checkbox.component.spec.ts +43 -0
- package/src/lib/components/input/input-checkbox/input-checkbox.component.ts +112 -0
- package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.html +43 -0
- package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.scss +140 -0
- package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.spec.ts +62 -0
- package/src/lib/components/input/input-checkbox-group/input-checkbox-group.component.ts +136 -0
- package/src/lib/components/input/input-clock-picker/input-clock-picker.component.html +81 -0
- package/src/lib/components/input/input-clock-picker/input-clock-picker.component.scss +228 -0
- package/src/lib/components/input/input-clock-picker/input-clock-picker.component.spec.ts +62 -0
- package/src/lib/components/input/input-clock-picker/input-clock-picker.component.ts +178 -0
- package/src/lib/components/input/input-consts.ts +132 -0
- package/src/lib/components/input/input-date/input-date-validators.ts +41 -0
- package/src/lib/components/input/input-date/input-date.component.html +41 -0
- package/src/lib/components/input/input-date/input-date.component.scss +95 -0
- package/src/lib/components/input/input-date/input-date.component.spec.ts +43 -0
- package/src/lib/components/input/input-date/input-date.component.ts +359 -0
- package/src/lib/components/input/input-date-time/input-date-time.component.html +70 -0
- package/src/lib/components/input/input-date-time/input-date-time.component.scss +133 -0
- package/src/lib/components/input/input-date-time/input-date-time.component.spec.ts +36 -0
- package/src/lib/components/input/input-date-time/input-date-time.component.ts +387 -0
- package/src/lib/components/input/input-file-upload/input-file-upload.component.html +89 -0
- package/src/lib/components/input/input-file-upload/input-file-upload.component.scss +171 -0
- package/src/lib/components/input/input-file-upload/input-file-upload.component.spec.ts +43 -0
- package/src/lib/components/input/input-file-upload/input-file-upload.component.ts +351 -0
- package/src/lib/components/input/input-interface.ts +8 -0
- package/src/lib/components/input/input-number/input-number-validators.ts +0 -0
- package/src/lib/components/input/input-number/input-number.component.html +51 -0
- package/src/lib/components/input/input-number/input-number.component.scss +140 -0
- package/src/lib/components/input/input-number/input-number.component.spec.ts +44 -0
- package/src/lib/components/input/input-number/input-number.component.ts +343 -0
- package/src/lib/components/input/input-radio-group/input-radio-group.component.html +44 -0
- package/src/lib/components/input/input-radio-group/input-radio-group.component.scss +139 -0
- package/src/lib/components/input/input-radio-group/input-radio-group.component.spec.ts +58 -0
- package/src/lib/components/input/input-radio-group/input-radio-group.component.ts +132 -0
- package/src/lib/components/input/input-slider/input-slider.component.html +111 -0
- package/src/lib/components/input/input-slider/input-slider.component.scss +203 -0
- package/src/lib/components/input/input-slider/input-slider.component.spec.ts +46 -0
- package/src/lib/components/input/input-slider/input-slider.component.ts +410 -0
- package/src/lib/components/input/input-text/input-text-validators.ts +67 -0
- package/src/lib/components/input/input-text/input-text.component.html +71 -0
- package/src/lib/components/input/input-text/input-text.component.scss +118 -0
- package/src/lib/components/input/input-text/input-text.component.spec.ts +55 -0
- package/src/lib/components/input/input-text/input-text.component.ts +215 -0
- package/src/lib/components/input/input-time/input-time-validators.ts +42 -0
- package/src/lib/components/input/input-time/input-time.component.html +92 -0
- package/src/lib/components/input/input-time/input-time.component.scss +191 -0
- package/src/lib/components/input/input-time/input-time.component.spec.ts +39 -0
- package/src/lib/components/input/input-time/input-time.component.ts +691 -0
- package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.html +36 -0
- package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.scss +121 -0
- package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.spec.ts +54 -0
- package/src/lib/components/input/input-toggle-switch/input-toggle-switch.component.ts +117 -0
- package/src/lib/components/input/input-type.ts +18 -0
- package/src/lib/components/input/input-validation/input-validation.component.html +19 -0
- package/src/lib/components/input/input-validation/input-validation.component.scss +39 -0
- package/src/lib/components/input/input-validation/input-validation.component.spec.ts +45 -0
- package/src/lib/components/input/input-validation/input-validation.component.ts +13 -0
- package/src/lib/components/input/input.pipe.ts +14 -0
- package/src/lib/components/layout/container/container.component.html +1 -0
- package/src/lib/components/layout/container/container.component.scss +33 -0
- package/src/lib/components/layout/container/container.component.ts +32 -0
- package/src/lib/components/layout/container/container.type.ts +1 -0
- package/src/lib/components/layout/divider/divider.component.html +1 -0
- package/src/lib/components/layout/divider/divider.component.scss +60 -0
- package/src/lib/components/layout/divider/divider.component.ts +38 -0
- package/src/lib/components/layout/divider/divider.type.ts +2 -0
- package/src/lib/components/layout/section/section.component.html +21 -0
- package/src/lib/components/layout/section/section.component.scss +43 -0
- package/src/lib/components/layout/section/section.component.ts +33 -0
- package/src/lib/components/layout/section/section.type.ts +2 -0
- package/src/lib/components/layout/separator/separator.component.html +9 -0
- package/src/lib/components/layout/separator/separator.component.scss +52 -0
- package/src/lib/components/layout/separator/separator.component.ts +25 -0
- package/src/lib/components/layout/separator/separator.type.ts +1 -0
- package/src/lib/components/loader/content-blur/content-blur.component.html +13 -0
- package/src/lib/components/loader/content-blur/content-blur.component.scss +43 -0
- package/src/lib/components/loader/content-blur/content-blur.component.spec.ts +42 -0
- package/src/lib/components/loader/content-blur/content-blur.component.ts +34 -0
- package/src/lib/components/loader/loader.type.ts +2 -0
- package/src/lib/components/loader/progress-bar/progress-bar.component.html +26 -0
- package/src/lib/components/loader/progress-bar/progress-bar.component.scss +151 -0
- package/src/lib/components/loader/progress-bar/progress-bar.component.spec.ts +47 -0
- package/src/lib/components/loader/progress-bar/progress-bar.component.ts +28 -0
- package/src/lib/components/loader/progress-bar/progress-bar.type.ts +8 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.component.html +12 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.component.scss +202 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.component.spec.ts +55 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.component.ts +73 -0
- package/src/lib/components/loader/pulse-loader/pulse-loader.type.ts +6 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.html +13 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.scss +113 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.spec.ts +37 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.component.ts +51 -0
- package/src/lib/components/loader/skeleton-loader/skeleton-loader.type.ts +6 -0
- package/src/lib/components/loader/spinner/spinner.component.html +20 -0
- package/src/lib/components/loader/spinner/spinner.component.scss +137 -0
- package/src/lib/components/loader/spinner/spinner.component.spec.ts +43 -0
- package/src/lib/components/loader/spinner/spinner.component.ts +32 -0
- package/src/lib/components/loader/spinner/spinner.type.ts +6 -0
- package/src/lib/components/modal/modal.component.html +47 -0
- package/src/lib/components/modal/modal.component.scss +139 -0
- package/src/lib/components/modal/modal.component.spec.ts +60 -0
- package/src/lib/components/modal/modal.component.ts +83 -0
- package/src/lib/components/modal/modal.type.ts +9 -0
- package/src/lib/components/morph/blob-moph/blob-moprh.component.spec.ts +79 -0
- package/src/lib/components/morph/blob-moph/blob-moprh.component.ts +96 -0
- package/src/lib/components/morph/blob-moph/blob-morph.component.html +34 -0
- package/src/lib/components/morph/blob-moph/blob-morph.component.scss +7 -0
- package/src/lib/components/morph/morph.abstract.ts +13 -0
- package/src/lib/components/pagination/pagination.interface.ts +4 -0
- package/src/lib/components/pagination/small-pagination/small-pagination.component.html +61 -0
- package/src/lib/components/pagination/small-pagination/small-pagination.component.scss +187 -0
- package/src/lib/components/pagination/small-pagination/small-pagination.component.spec.ts +88 -0
- package/src/lib/components/pagination/small-pagination/small-pagination.component.ts +177 -0
- package/src/lib/components/selection-lists/multi-select/multi-select.component.html +170 -0
- package/src/lib/components/selection-lists/multi-select/multi-select.component.scss +312 -0
- package/src/lib/components/selection-lists/multi-select/multi-select.component.spec.ts +61 -0
- package/src/lib/components/selection-lists/multi-select/multi-select.component.ts +372 -0
- package/src/lib/components/selection-lists/selection-list/selection-list.component.html +125 -0
- package/src/lib/components/selection-lists/selection-list/selection-list.component.scss +267 -0
- package/src/lib/components/selection-lists/selection-list/selection-list.component.spec.ts +66 -0
- package/src/lib/components/selection-lists/selection-list/selection-list.component.ts +315 -0
- package/src/lib/components/selection-lists/selection-lists-base.ts +35 -0
- package/src/lib/components/selection-lists/selection-lists-const.ts +17 -0
- package/src/lib/components/selection-lists/selection-lists-interface.ts +7 -0
- package/src/lib/components/selection-lists/selection-lists.type.ts +1 -0
- package/src/lib/components/side-nav/side-nav.component.html +101 -0
- package/src/lib/components/side-nav/side-nav.component.scss +295 -0
- package/src/lib/components/side-nav/side-nav.component.spec.ts +0 -0
- package/src/lib/components/side-nav/side-nav.component.ts +18 -0
- package/src/lib/components/side-nav/side-nav.type.ts +28 -0
- package/src/lib/components/snackbar/snackbar.component.html +33 -0
- package/src/lib/components/snackbar/snackbar.component.scss +195 -0
- package/src/lib/components/snackbar/snackbar.component.ts +112 -0
- package/src/lib/components/snackbar/snackbar.type.ts +27 -0
- package/src/lib/components/status/chip/chip.component.html +51 -0
- package/src/lib/components/status/chip/chip.component.scss +149 -0
- package/src/lib/components/status/chip/chip.component.spec.ts +62 -0
- package/src/lib/components/status/chip/chip.component.ts +83 -0
- package/src/lib/components/status/chip/chip.type.ts +42 -0
- package/src/lib/components/status/directives/badge/badge.directive.spec.ts +60 -0
- package/src/lib/components/status/directives/badge/badge.directive.ts +190 -0
- package/src/lib/components/status/directives/badge/badge.interface.ts +19 -0
- package/src/lib/components/status/pill/pill.component.html +40 -0
- package/src/lib/components/status/pill/pill.component.scss +113 -0
- package/src/lib/components/status/pill/pill.component.spec.ts +47 -0
- package/src/lib/components/status/pill/pill.component.ts +83 -0
- package/src/lib/components/status/pill/pill.type.ts +42 -0
- package/src/lib/components/status/status.interface.ts +57 -0
- package/src/lib/components/status/status.type.ts +62 -0
- package/src/lib/components/status/tag/tag.component.html +39 -0
- package/src/lib/components/status/tag/tag.component.scss +140 -0
- package/src/lib/components/status/tag/tag.component.spec.ts +47 -0
- package/src/lib/components/status/tag/tag.component.ts +83 -0
- package/src/lib/components/status/tag/tag.type.ts +42 -0
- package/src/lib/components/stepper/stepper.component.html +83 -0
- package/src/lib/components/stepper/stepper.component.scss +196 -0
- package/src/lib/components/stepper/stepper.component.ts +482 -0
- package/src/lib/components/stepper/stepper.type.ts +60 -0
- package/src/lib/components/table/table.component.html +438 -0
- package/src/lib/components/table/table.component.scss +259 -0
- package/src/lib/components/table/table.component.spec.ts +117 -0
- package/src/lib/components/table/table.component.ts +215 -0
- package/src/lib/components/table/table.enum.ts +4 -0
- package/src/lib/components/table/table.function.ts +47 -0
- package/src/lib/components/table/table.interface.ts +143 -0
- package/src/lib/components/table/table.pipe.ts +62 -0
- package/src/lib/components/table/table.type.ts +15 -0
- package/src/lib/components/tabs/tabs.component.html +88 -0
- package/src/lib/components/tabs/tabs.component.scss +305 -0
- package/src/lib/components/tabs/tabs.component.spec.ts +94 -0
- package/src/lib/components/tabs/tabs.component.ts +282 -0
- package/src/lib/components/tabs/tabs.type.ts +81 -0
- package/src/lib/components/title-bar/title-bar.component.html +21 -0
- package/src/lib/components/title-bar/title-bar.component.scss +139 -0
- package/src/lib/components/title-bar/title-bar.component.spec.ts +44 -0
- package/src/lib/components/title-bar/title-bar.component.ts +13 -0
- package/src/lib/components/toast/toast.component.html +36 -0
- package/src/lib/components/toast/toast.component.scss +241 -0
- package/src/lib/components/toast/toast.component.ts +165 -0
- package/src/lib/components/toast/toast.type.ts +37 -0
- package/src/lib/components/toast-stack/toast-stack.component.html +30 -0
- package/src/lib/components/toast-stack/toast-stack.component.scss +35 -0
- package/src/lib/components/toast-stack/toast-stack.component.ts +51 -0
- package/src/lib/consts/country-prefix.ts +244 -0
- package/src/lib/directives/tooltip/popover.directive.ts +274 -0
- package/src/lib/directives/tooltip/tooltip.directive.spec.ts +86 -0
- package/src/lib/directives/tooltip/tooltip.directive.ts +234 -0
- package/src/lib/directives/tooltip/tooltip.interface.ts +29 -0
- package/src/lib/directives/tooltip/tooltip.type.ts +9 -0
- package/src/lib/interfaces/common.interfaces.ts +4 -0
- package/src/lib/pipes/chunk.pipe.ts +16 -0
- package/src/lib/pipes/safe-html.pipe.ts +14 -0
- package/src/lib/pipes/sanitize-html.pipe.ts +23 -0
- package/src/lib/types/base.types.ts +23 -0
- package/src/lib/types/common.types.ts +98 -0
- package/src/lib/types/form.types.ts +5 -0
- package/src/lib/utils/common.utils.ts +53 -0
- package/src/lib/utils/date.utils.ts +474 -0
- package/src/lib/utils/number.utils.ts +16 -0
- package/src/lib/utils/uuid.utils.ts +39 -0
- package/src/public-api.ts +114 -0
- package/tsconfig.lib.json +17 -0
- package/tsconfig.lib.prod.json +10 -0
- package/tsconfig.spec.json +9 -0
- package/fesm2022/tacdaed-fragments.mjs +0 -8928
- package/fesm2022/tacdaed-fragments.mjs.map +0 -1
- package/index.d.ts +0 -3929
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AfterViewInit,
|
|
3
|
+
ChangeDetectionStrategy,
|
|
4
|
+
ChangeDetectorRef,
|
|
5
|
+
Component,
|
|
6
|
+
ElementRef,
|
|
7
|
+
EventEmitter,
|
|
8
|
+
Input,
|
|
9
|
+
OnChanges,
|
|
10
|
+
OnDestroy,
|
|
11
|
+
Output,
|
|
12
|
+
SimpleChanges,
|
|
13
|
+
Type,
|
|
14
|
+
ViewChild,
|
|
15
|
+
inject,
|
|
16
|
+
} from '@angular/core';
|
|
17
|
+
|
|
18
|
+
import hljs from 'highlight.js';
|
|
19
|
+
import { generateUniqueId } from '../../utils/uuid.utils';
|
|
20
|
+
import { CodeBlockConfig, CodeBlockHeader } from './code-block.interface';
|
|
21
|
+
import { CodeBlockBody, THLJSLanguage } from './code-block.type';
|
|
22
|
+
|
|
23
|
+
@Component({
|
|
24
|
+
selector: 'frg-code-block',
|
|
25
|
+
templateUrl: './code-block.component.html',
|
|
26
|
+
styleUrls: ['./code-block.component.scss'],
|
|
27
|
+
imports: [],
|
|
28
|
+
changeDetection: ChangeDetectionStrategy.OnPush
|
|
29
|
+
})
|
|
30
|
+
export class CodeBlockComponent implements AfterViewInit, OnChanges, OnDestroy {
|
|
31
|
+
private readonly cdr: ChangeDetectorRef = inject(ChangeDetectorRef);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Configuration options for the code block.
|
|
35
|
+
*/
|
|
36
|
+
@Input() public config: CodeBlockConfig | undefined = undefined;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Emitted when the code block is closed.
|
|
40
|
+
*/
|
|
41
|
+
@Output() public closed = new EventEmitter<void>();
|
|
42
|
+
|
|
43
|
+
protected copied = false;
|
|
44
|
+
private copyResetId: ReturnType<typeof setTimeout> | null = null;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Reference to the code element in the template.
|
|
48
|
+
*/
|
|
49
|
+
@ViewChild('codeElement', { static: false })
|
|
50
|
+
codeElement?: ElementRef<HTMLElement>;
|
|
51
|
+
/**
|
|
52
|
+
* Reference to the container element in the template.
|
|
53
|
+
*/
|
|
54
|
+
@ViewChild('container', { static: false })
|
|
55
|
+
containerElement?: ElementRef<HTMLElement>;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Indicates if the code block has a footer.
|
|
59
|
+
*/
|
|
60
|
+
protected get hasConfig(): boolean {
|
|
61
|
+
return !!this.config;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Returns the header configuration of the code block.
|
|
66
|
+
* This includes properties like title, minimize, fullscreen, and close options.
|
|
67
|
+
* @return {CodeBlockHeader | undefined} The header configuration or undefined if not set.
|
|
68
|
+
* @memberof CodeBlockComponent
|
|
69
|
+
*/
|
|
70
|
+
protected get header(): CodeBlockHeader | undefined {
|
|
71
|
+
return this.config?.header;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns the body of the code block, which can be either text or a component.
|
|
76
|
+
* @return {CodeBlockBody | undefined} The body configuration or undefined if not set.
|
|
77
|
+
* @memberof CodeBlockComponent
|
|
78
|
+
*/
|
|
79
|
+
protected get title(): string | undefined {
|
|
80
|
+
return this.config?.header?.title;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Returns the body configuration of the code block.
|
|
85
|
+
* This includes properties like content and language.
|
|
86
|
+
* @return {CodeBlockBody | undefined} The body configuration or undefined if not set.
|
|
87
|
+
* @memberof CodeBlockComponent
|
|
88
|
+
*/
|
|
89
|
+
protected get body(): CodeBlockBody | undefined {
|
|
90
|
+
return this.config?.body;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Returns the type of content in the body of the code block.
|
|
95
|
+
* This can be either 'text' for plain text content or 'component' for a component.
|
|
96
|
+
* @return {'text' | 'component' | undefined} The type of content or undefined if not set.
|
|
97
|
+
* @memberof CodeBlockComponent
|
|
98
|
+
*/
|
|
99
|
+
protected get type(): 'text' | 'component' | undefined {
|
|
100
|
+
return this.config?.body?.type;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Returns the component type in the body of the code block.
|
|
105
|
+
* @return {Type<T> | undefined} The component type or undefined if not set.
|
|
106
|
+
* @memberof CodeBlockComponent
|
|
107
|
+
*/
|
|
108
|
+
protected get component(): Type<unknown> | undefined {
|
|
109
|
+
return this.config?.body?.component;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Returns the inputs for the component in the body of the code block.
|
|
114
|
+
* @return {Record<string, unknown> | undefined} The inputs or undefined if not set.
|
|
115
|
+
* @memberof CodeBlockComponent
|
|
116
|
+
*/
|
|
117
|
+
protected get inputs(): Record<string, unknown> | undefined {
|
|
118
|
+
return this.config?.body?.inputs;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Returns the content for the code block.
|
|
123
|
+
* @return {string | undefined} The content or undefined if not set.
|
|
124
|
+
* @memberof CodeBlockComponent
|
|
125
|
+
*/
|
|
126
|
+
protected get content(): string | undefined {
|
|
127
|
+
return this.config?.body?.content;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Returns the programming language for the code block.
|
|
132
|
+
* @return {THLJSLanguage | undefined} The language or undefined if not set.
|
|
133
|
+
* @memberof CodeBlockComponent
|
|
134
|
+
*/
|
|
135
|
+
protected get language(): THLJSLanguage | undefined {
|
|
136
|
+
return this.config?.body?.language;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Returns the lines to highlight in the code block.
|
|
141
|
+
* @return {string | undefined} The highlight lines or undefined if not set.
|
|
142
|
+
* @memberof CodeBlockComponent
|
|
143
|
+
*/
|
|
144
|
+
protected get highlightLines(): string | undefined {
|
|
145
|
+
return this.config?.body?.highlightLines;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
protected get showCopyButton(): boolean {
|
|
149
|
+
if (this.config?.body?.type !== 'text' || !this.header) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
return this.header.showCopy ?? true;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
protected get copyLabel(): string {
|
|
156
|
+
return this.header?.copyLabel ?? 'Copy';
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
protected get copiedLabel(): string {
|
|
160
|
+
return this.header?.copiedLabel ?? 'Copied';
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
ngAfterViewInit() {
|
|
164
|
+
if (this.config?.body?.type === 'text') {
|
|
165
|
+
this.highlightCode();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
ngOnChanges(changes: SimpleChanges) {
|
|
170
|
+
if (changes['config']) {
|
|
171
|
+
if (!this.config?.id) {
|
|
172
|
+
this.config = {
|
|
173
|
+
...this.config,
|
|
174
|
+
id: generateUniqueId('codeblock'),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const prevContent = changes['config'].previousValue?.body?.content;
|
|
179
|
+
const newContent = changes['config'].currentValue?.body?.content;
|
|
180
|
+
|
|
181
|
+
if (prevContent !== newContent && this.config?.body?.type === 'text') {
|
|
182
|
+
this.highlightCode();
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
ngOnDestroy(): void {
|
|
188
|
+
if (this.copyResetId) {
|
|
189
|
+
clearTimeout(this.copyResetId);
|
|
190
|
+
this.copyResetId = null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
protected copyToClipboard(): void {
|
|
195
|
+
if (this.config?.body?.type !== 'text') {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const text = this.getCopyContent();
|
|
200
|
+
if (!text) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const onSuccess = () => {
|
|
205
|
+
this.copied = true;
|
|
206
|
+
this.cdr.markForCheck();
|
|
207
|
+
if (this.copyResetId) {
|
|
208
|
+
clearTimeout(this.copyResetId);
|
|
209
|
+
}
|
|
210
|
+
this.copyResetId = setTimeout(() => {
|
|
211
|
+
this.copied = false;
|
|
212
|
+
this.cdr.markForCheck();
|
|
213
|
+
}, 1500);
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const canUseClipboard = window.isSecureContext && navigator.clipboard && typeof navigator.clipboard.writeText === 'function';
|
|
217
|
+
if (canUseClipboard) {
|
|
218
|
+
navigator.clipboard.writeText(text).then(onSuccess).catch(() => {
|
|
219
|
+
this.fallbackCopy(text, onSuccess);
|
|
220
|
+
});
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
this.fallbackCopy(text, onSuccess);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Highlights the code in the code block.
|
|
229
|
+
* This method uses the highlight.js library to apply syntax highlighting.
|
|
230
|
+
*/
|
|
231
|
+
private highlightCode() {
|
|
232
|
+
if (this.config?.body?.type === 'text' && this.codeElement) {
|
|
233
|
+
let code = this.config.body.content ?? '';
|
|
234
|
+
|
|
235
|
+
code = this.dedent(code).trim();
|
|
236
|
+
if(this.config.body.hasNumberLine){
|
|
237
|
+
code = this.addNumberLines(code);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
this.codeElement.nativeElement.textContent = code;
|
|
241
|
+
hljs.highlightElement(this.codeElement.nativeElement);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private getCopyContent(): string {
|
|
246
|
+
let code = this.config?.body?.content ?? '';
|
|
247
|
+
code = this.dedent(code).trim();
|
|
248
|
+
return code;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private fallbackCopy(text: string, onSuccess: () => void): void {
|
|
252
|
+
const textarea = document.createElement('textarea');
|
|
253
|
+
textarea.value = text;
|
|
254
|
+
textarea.setAttribute('readonly', 'true');
|
|
255
|
+
textarea.style.position = 'absolute';
|
|
256
|
+
textarea.style.left = '-9999px';
|
|
257
|
+
document.body.appendChild(textarea);
|
|
258
|
+
textarea.focus();
|
|
259
|
+
textarea.select();
|
|
260
|
+
textarea.setSelectionRange(0, textarea.value.length);
|
|
261
|
+
const copied = document.execCommand('copy');
|
|
262
|
+
document.body.removeChild(textarea);
|
|
263
|
+
if (copied) {
|
|
264
|
+
onSuccess();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Dedents a given string by removing common leading whitespace.
|
|
270
|
+
* @param str The input string to dedent.
|
|
271
|
+
* @returns The dedented string.
|
|
272
|
+
*/
|
|
273
|
+
private dedent(str: string): string {
|
|
274
|
+
const lines = str.replace(/\t/g, ' ').split('\n');
|
|
275
|
+
|
|
276
|
+
while (lines.length && lines[0].trim() === '') lines.shift();
|
|
277
|
+
while (lines.length && lines[lines.length - 1].trim() === '') lines.pop();
|
|
278
|
+
|
|
279
|
+
const minIndent = Math.min(
|
|
280
|
+
...lines
|
|
281
|
+
.filter(line => line.trim().length > 0)
|
|
282
|
+
.map(line => {
|
|
283
|
+
const match = /^(\s*)/.exec(line);
|
|
284
|
+
return match ? match[0].length : 0;
|
|
285
|
+
})
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
return lines.map(line => line.slice(minIndent)).join('\n');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private readonly addNumberLines = (str: string): string => {
|
|
292
|
+
const lines = str.split('\n');
|
|
293
|
+
const maxLength = lines.length.toString().length;
|
|
294
|
+
|
|
295
|
+
return lines
|
|
296
|
+
.map((line, index) => {
|
|
297
|
+
const lineNumber = (index + 1).toString().padStart(maxLength, ' ');
|
|
298
|
+
return `${lineNumber} | ${line}`;
|
|
299
|
+
})
|
|
300
|
+
.join('\n');
|
|
301
|
+
};
|
|
302
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CodeBlockBody } from './code-block.type';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the code block component.
|
|
5
|
+
*/
|
|
6
|
+
export interface CodeBlockConfig {
|
|
7
|
+
id?: string;
|
|
8
|
+
header?: CodeBlockHeader;
|
|
9
|
+
body?: CodeBlockBody;
|
|
10
|
+
footer?: CodeBlockFooter;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Configuration options for the code block header.
|
|
15
|
+
*/
|
|
16
|
+
export interface CodeBlockHeader {
|
|
17
|
+
title?: string;
|
|
18
|
+
showCopy?: boolean;
|
|
19
|
+
copyLabel?: string;
|
|
20
|
+
copiedLabel?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Configuration options for the code block footer.
|
|
25
|
+
*/
|
|
26
|
+
export interface CodeBlockFooter {
|
|
27
|
+
text?: string;
|
|
28
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { Type } from '@angular/core';
|
|
2
|
+
import { XOR } from '../../types/common.types';
|
|
3
|
+
|
|
4
|
+
export type THLJSLanguage =
|
|
5
|
+
| 'html'
|
|
6
|
+
| 'xml'
|
|
7
|
+
| 'xhtml'
|
|
8
|
+
| 'svg'
|
|
9
|
+
| 'css'
|
|
10
|
+
| 'scss'
|
|
11
|
+
| 'less'
|
|
12
|
+
| 'javascript'
|
|
13
|
+
| 'typescript'
|
|
14
|
+
| 'json'
|
|
15
|
+
| 'markdown'
|
|
16
|
+
| 'yaml'
|
|
17
|
+
| 'yml'
|
|
18
|
+
| 'php'
|
|
19
|
+
| 'java'
|
|
20
|
+
| 'python'
|
|
21
|
+
| 'ruby'
|
|
22
|
+
| 'c'
|
|
23
|
+
| 'cpp'
|
|
24
|
+
| 'csharp'
|
|
25
|
+
| 'go'
|
|
26
|
+
| 'rust'
|
|
27
|
+
| 'kotlin'
|
|
28
|
+
| 'perl'
|
|
29
|
+
| 'swift'
|
|
30
|
+
| 'dart'
|
|
31
|
+
| 'scala'
|
|
32
|
+
| 'haskell'
|
|
33
|
+
| 'erlang'
|
|
34
|
+
| 'bash'
|
|
35
|
+
| 'shell'
|
|
36
|
+
| 'powershell'
|
|
37
|
+
| 'docker'
|
|
38
|
+
| 'makefile'
|
|
39
|
+
| 'git'
|
|
40
|
+
| 'ini'
|
|
41
|
+
| 'toml'
|
|
42
|
+
| 'sql'
|
|
43
|
+
| 'graphql'
|
|
44
|
+
| 'json5'
|
|
45
|
+
| 'text'
|
|
46
|
+
| 'diff'
|
|
47
|
+
| 'http'
|
|
48
|
+
| 'nginx'
|
|
49
|
+
| 'apache'
|
|
50
|
+
| 'log'
|
|
51
|
+
| 'env';
|
|
52
|
+
|
|
53
|
+
type TextContent = {
|
|
54
|
+
type: 'text';
|
|
55
|
+
content: string;
|
|
56
|
+
language?: THLJSLanguage;
|
|
57
|
+
highlightLines?: string;
|
|
58
|
+
hasNumberLine?: boolean;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
type ComponentContent<
|
|
62
|
+
T = unknown,
|
|
63
|
+
I extends Record<string, unknown> = Record<string, unknown>,
|
|
64
|
+
> = {
|
|
65
|
+
type: 'component';
|
|
66
|
+
component: Type<T>;
|
|
67
|
+
inputs?: I;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export type CodeBlockBody<
|
|
71
|
+
T = unknown,
|
|
72
|
+
I extends Record<string, unknown> = Record<string, unknown>,
|
|
73
|
+
> = XOR<TextContent, ComponentContent<T, I>>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<div
|
|
2
|
+
class="frg-sparkle-field"
|
|
3
|
+
[style.--frg-sparkle-color]="color || null"
|
|
4
|
+
>
|
|
5
|
+
<span
|
|
6
|
+
#sparkle
|
|
7
|
+
*ngFor="let sparkle of sparkles"
|
|
8
|
+
class="frg-sparkle"
|
|
9
|
+
[style.left.%]="sparkle.x"
|
|
10
|
+
[style.top.%]="sparkle.y"
|
|
11
|
+
[style.width.px]="sparkle.size"
|
|
12
|
+
[style.height.px]="sparkle.size"
|
|
13
|
+
></span>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
:host {
|
|
2
|
+
display: inline-block;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.frg-sparkle-field {
|
|
6
|
+
position: relative;
|
|
7
|
+
overflow: hidden;
|
|
8
|
+
width: 100%;
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.frg-sparkle {
|
|
13
|
+
position: absolute;
|
|
14
|
+
border-radius: 999px;
|
|
15
|
+
background: var(--frg-sparkle-color, currentColor);
|
|
16
|
+
opacity: 0.6;
|
|
17
|
+
filter: blur(0.2px);
|
|
18
|
+
transform: translateZ(0);
|
|
19
|
+
will-change: transform, opacity;
|
|
20
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { By } from '@angular/platform-browser';
|
|
3
|
+
import { SparkleFieldComponent } from './sparkle-field.component';
|
|
4
|
+
|
|
5
|
+
describe('SparkleFieldComponent', () => {
|
|
6
|
+
let fixture: ComponentFixture<SparkleFieldComponent>;
|
|
7
|
+
let component: SparkleFieldComponent;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
imports: [SparkleFieldComponent],
|
|
12
|
+
}).compileComponents();
|
|
13
|
+
|
|
14
|
+
fixture = TestBed.createComponent(SparkleFieldComponent);
|
|
15
|
+
component = fixture.componentInstance;
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('renders the configured number of sparkles', () => {
|
|
19
|
+
component.count = 5;
|
|
20
|
+
|
|
21
|
+
fixture.detectChanges();
|
|
22
|
+
|
|
23
|
+
const sparkles = fixture.debugElement.queryAll(By.css('.frg-sparkle'));
|
|
24
|
+
expect(sparkles.length).toBe(5);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('applies width and height styles to the field', () => {
|
|
28
|
+
component.width = 200;
|
|
29
|
+
component.height = 120;
|
|
30
|
+
|
|
31
|
+
fixture.detectChanges();
|
|
32
|
+
|
|
33
|
+
const host = fixture.nativeElement as HTMLElement;
|
|
34
|
+
|
|
35
|
+
expect(host.style.width).toBe('200px');
|
|
36
|
+
expect(host.style.height).toBe('120px');
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { NgFor } from '@angular/common';
|
|
2
|
+
import {
|
|
3
|
+
AfterViewInit,
|
|
4
|
+
Component,
|
|
5
|
+
ElementRef,
|
|
6
|
+
HostBinding,
|
|
7
|
+
Input,
|
|
8
|
+
OnChanges,
|
|
9
|
+
OnDestroy,
|
|
10
|
+
OnInit,
|
|
11
|
+
QueryList,
|
|
12
|
+
SimpleChanges,
|
|
13
|
+
ViewChildren,
|
|
14
|
+
} from '@angular/core';
|
|
15
|
+
import { animate } from 'animejs';
|
|
16
|
+
import { Subscription } from 'rxjs';
|
|
17
|
+
|
|
18
|
+
interface Sparkle {
|
|
19
|
+
x: number;
|
|
20
|
+
y: number;
|
|
21
|
+
size: number;
|
|
22
|
+
delay: number;
|
|
23
|
+
duration: number;
|
|
24
|
+
driftX: number;
|
|
25
|
+
driftY: number;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Component({
|
|
29
|
+
selector: 'frg-sparkle-field',
|
|
30
|
+
templateUrl: './sparkle-field.component.html',
|
|
31
|
+
styleUrl: './sparkle-field.component.scss',
|
|
32
|
+
imports: [NgFor],
|
|
33
|
+
})
|
|
34
|
+
export class SparkleFieldComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
|
|
35
|
+
@Input() width: number | string = 260;
|
|
36
|
+
@Input() height: number | string = 160;
|
|
37
|
+
@Input() count = 12;
|
|
38
|
+
@Input() minSize = 2;
|
|
39
|
+
@Input() maxSize = 6;
|
|
40
|
+
@Input() drift = 18;
|
|
41
|
+
@Input() minDuration = 2400;
|
|
42
|
+
@Input() maxDuration = 5200;
|
|
43
|
+
@Input() loop = true;
|
|
44
|
+
@Input() color: string | null = null;
|
|
45
|
+
|
|
46
|
+
sparkles: Sparkle[] = [];
|
|
47
|
+
|
|
48
|
+
@ViewChildren('sparkle')
|
|
49
|
+
sparkleRefs!: QueryList<ElementRef<HTMLSpanElement>>;
|
|
50
|
+
|
|
51
|
+
private sparkleAnimations: Array<ReturnType<typeof animate>> = [];
|
|
52
|
+
private sparkleChangesSub: Subscription | null = null;
|
|
53
|
+
private readonly fallbackWidth = 260;
|
|
54
|
+
private readonly fallbackHeight = 160;
|
|
55
|
+
|
|
56
|
+
@HostBinding('style.width') get hostWidth(): string {
|
|
57
|
+
return this.widthStyle;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@HostBinding('style.height') get hostHeight(): string {
|
|
61
|
+
return this.heightStyle;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@HostBinding('style.minWidth') get hostMinWidth(): string | null {
|
|
65
|
+
return this.needsMinSize(this.width) ? `${this.fallbackWidth}px` : null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@HostBinding('style.minHeight') get hostMinHeight(): string | null {
|
|
69
|
+
return this.needsMinSize(this.height) ? `${this.fallbackHeight}px` : null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
ngOnInit(): void {
|
|
73
|
+
this.buildSparkles();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ngOnChanges(changes: SimpleChanges): void {
|
|
77
|
+
if (
|
|
78
|
+
changes['count'] ||
|
|
79
|
+
changes['minSize'] ||
|
|
80
|
+
changes['maxSize'] ||
|
|
81
|
+
changes['drift'] ||
|
|
82
|
+
changes['minDuration'] ||
|
|
83
|
+
changes['maxDuration'] ||
|
|
84
|
+
changes['loop']
|
|
85
|
+
) {
|
|
86
|
+
this.buildSparkles();
|
|
87
|
+
this.restartAnimation();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
ngAfterViewInit(): void {
|
|
92
|
+
this.sparkleChangesSub = this.sparkleRefs.changes.subscribe(() =>
|
|
93
|
+
this.restartAnimation()
|
|
94
|
+
);
|
|
95
|
+
this.restartAnimation();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
ngOnDestroy(): void {
|
|
99
|
+
this.sparkleAnimations.forEach((animation) => animation.pause());
|
|
100
|
+
this.sparkleChangesSub?.unsubscribe();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
private buildSparkles(): void {
|
|
104
|
+
const count = Math.max(0, Math.floor(this.count));
|
|
105
|
+
const minSize = Math.min(this.minSize, this.maxSize);
|
|
106
|
+
const maxSize = Math.max(this.minSize, this.maxSize);
|
|
107
|
+
const minDuration = Math.min(this.minDuration, this.maxDuration);
|
|
108
|
+
const maxDuration = Math.max(this.minDuration, this.maxDuration);
|
|
109
|
+
|
|
110
|
+
this.sparkles = Array.from({ length: count }, () => ({
|
|
111
|
+
x: this.randomInRange(0, 100),
|
|
112
|
+
y: this.randomInRange(0, 100),
|
|
113
|
+
size: this.randomInRange(minSize, maxSize),
|
|
114
|
+
delay: this.randomInRange(0, 900),
|
|
115
|
+
duration: this.randomInRange(minDuration, maxDuration),
|
|
116
|
+
driftX: this.randomInRange(-this.drift, this.drift),
|
|
117
|
+
driftY: this.randomInRange(-this.drift, this.drift),
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
private restartAnimation(): void {
|
|
122
|
+
if (!this.sparkleRefs || this.sparkleRefs.length === 0) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
this.sparkleAnimations.forEach((animation) => animation.pause());
|
|
127
|
+
this.sparkleAnimations = [];
|
|
128
|
+
|
|
129
|
+
const targets = this.sparkleRefs.toArray();
|
|
130
|
+
|
|
131
|
+
targets.forEach((ref, i) => {
|
|
132
|
+
const sparkle = this.sparkles[i];
|
|
133
|
+
if (!sparkle) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const animation = animate(ref.nativeElement, {
|
|
138
|
+
translateX: [-sparkle.driftX, sparkle.driftX],
|
|
139
|
+
translateY: [-sparkle.driftY, sparkle.driftY],
|
|
140
|
+
scale: [0.7, 1.2],
|
|
141
|
+
opacity: [0.35, 1],
|
|
142
|
+
duration: sparkle.duration ?? 3000,
|
|
143
|
+
alternate: true,
|
|
144
|
+
loop: this.loop,
|
|
145
|
+
ease: 'inOut',
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
if (sparkle.delay > 0) {
|
|
149
|
+
animation.seek(sparkle.delay % (sparkle.duration || 3000));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this.sparkleAnimations.push(animation);
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private randomInRange(min: number, max: number): number {
|
|
157
|
+
if (min === max) {
|
|
158
|
+
return min;
|
|
159
|
+
}
|
|
160
|
+
return min + Math.random() * (max - min);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
get widthStyle(): string {
|
|
164
|
+
return this.formatSize(this.width);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
get heightStyle(): string {
|
|
168
|
+
return this.formatSize(this.height);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
private formatSize(value: number | string): string {
|
|
172
|
+
if (typeof value === 'number') {
|
|
173
|
+
return `${value}px`;
|
|
174
|
+
}
|
|
175
|
+
return value;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private needsMinSize(value: number | string): boolean {
|
|
179
|
+
return typeof value === 'string' && value.trim().endsWith('%');
|
|
180
|
+
}
|
|
181
|
+
}
|