ngx-kit 7.1.0 → 7.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/angle-selector/README.md +34 -34
- package/box-shadow/README.md +33 -33
- package/color-picker/README.md +52 -52
- package/{shared → core}/README.md +117 -117
- package/data-table/README.md +120 -120
- package/date-picker/README.md +74 -74
- package/dialog/README.md +122 -92
- package/drag-resize/README.md +53 -55
- package/fesm2022/ngx-kit-angle-selector.mjs +9 -26
- package/fesm2022/ngx-kit-angle-selector.mjs.map +1 -1
- package/fesm2022/ngx-kit-box-shadow.mjs +330 -356
- package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -1
- package/fesm2022/ngx-kit-color-picker.mjs +132 -272
- package/fesm2022/ngx-kit-color-picker.mjs.map +1 -1
- package/fesm2022/{ngx-kit-shared.mjs → ngx-kit-core.mjs} +908 -277
- package/fesm2022/ngx-kit-core.mjs.map +1 -0
- package/fesm2022/ngx-kit-data-table.mjs +1 -1
- package/fesm2022/ngx-kit-data-table.mjs.map +1 -1
- package/fesm2022/ngx-kit-date-picker.mjs +34 -22
- package/fesm2022/ngx-kit-date-picker.mjs.map +1 -1
- package/fesm2022/ngx-kit-dialog.mjs +430 -331
- package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
- package/fesm2022/ngx-kit-drag-resize.mjs +193 -140
- package/fesm2022/ngx-kit-drag-resize.mjs.map +1 -1
- package/fesm2022/ngx-kit-drawer-menu.mjs +3 -3
- package/fesm2022/ngx-kit-drawer-menu.mjs.map +1 -1
- package/fesm2022/ngx-kit-dropzone.mjs.map +1 -1
- package/fesm2022/ngx-kit-form-field.mjs +9 -3
- package/fesm2022/ngx-kit-form-field.mjs.map +1 -1
- package/fesm2022/ngx-kit-gallery.mjs +3 -3
- package/fesm2022/ngx-kit-gallery.mjs.map +1 -1
- package/fesm2022/ngx-kit-gradient-picker.mjs +20 -38
- package/fesm2022/ngx-kit-gradient-picker.mjs.map +1 -1
- package/fesm2022/ngx-kit-grid-layout.mjs +32 -30
- package/fesm2022/ngx-kit-grid-layout.mjs.map +1 -1
- package/fesm2022/ngx-kit-image-editor.mjs +3 -3
- package/fesm2022/ngx-kit-image-editor.mjs.map +1 -1
- package/fesm2022/ngx-kit-menu.mjs +1 -1
- package/fesm2022/ngx-kit-menu.mjs.map +1 -1
- package/fesm2022/ngx-kit-message.mjs +2 -2
- package/fesm2022/ngx-kit-message.mjs.map +1 -1
- package/fesm2022/ngx-kit-notify.mjs +1 -1
- package/fesm2022/ngx-kit-notify.mjs.map +1 -1
- package/fesm2022/ngx-kit-time-picker.mjs +1 -1
- package/fesm2022/ngx-kit-time-picker.mjs.map +1 -1
- package/fesm2022/ngx-kit-virtual-scroll.mjs +2 -2
- package/fesm2022/ngx-kit-virtual-scroll.mjs.map +1 -1
- package/gallery/README.md +71 -71
- package/gradient-picker/README.md +41 -41
- package/grid-layout/README.md +64 -64
- package/image-editor/README.md +44 -44
- package/menu/README.md +85 -85
- package/message/README.md +70 -70
- package/notify/README.md +56 -56
- package/package.json +5 -9
- package/time-picker/README.md +89 -89
- package/types/ngx-kit-angle-selector.d.ts +13 -16
- package/types/ngx-kit-box-shadow.d.ts +37 -95
- package/types/ngx-kit-color-picker.d.ts +61 -58
- package/types/{ngx-kit-shared.d.ts → ngx-kit-core.d.ts} +194 -34
- package/types/ngx-kit-data-table.d.ts +2 -2
- package/types/ngx-kit-date-picker.d.ts +15 -12
- package/types/ngx-kit-dialog.d.ts +208 -107
- package/types/ngx-kit-drag-resize.d.ts +74 -47
- package/types/ngx-kit-form-field.d.ts +26 -23
- package/types/ngx-kit-gradient-picker.d.ts +4 -7
- package/types/ngx-kit-menu.d.ts +1 -1
- package/types/ngx-kit-time-picker.d.ts +1 -1
- package/virtual-scroll/README.md +199 -199
- package/fesm2022/ngx-kit-shared.mjs.map +0 -1
- package/fesm2022/ngx-kit-webflow.mjs +0 -709
- package/fesm2022/ngx-kit-webflow.mjs.map +0 -1
- package/types/ngx-kit-webflow.d.ts +0 -286
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule, isPlatformBrowser, DOCUMENT } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { EventEmitter, forwardRef, HostListener, ViewChild, Output, Input, ChangeDetectionStrategy, Component, inject, ChangeDetectorRef, InjectionToken, PLATFORM_ID, Inject, Injectable, DestroyRef, signal, computed } from '@angular/core';
|
|
4
|
+
import { EventEmitter, forwardRef, HostListener, ViewChild, Output, Input, ChangeDetectionStrategy, Component, inject, ChangeDetectorRef, InjectionToken, PLATFORM_ID, Inject, Injectable, DestroyRef, signal, computed, ApplicationRef, EnvironmentInjector, createComponent } from '@angular/core';
|
|
5
5
|
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, FormControl, Validators } from '@angular/forms';
|
|
6
6
|
|
|
7
7
|
function getOffsetPosition(evt, parent) {
|
|
@@ -672,40 +672,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
672
672
|
args: ['window:resize']
|
|
673
673
|
}] } });
|
|
674
674
|
|
|
675
|
-
function isPlainObject(value) {
|
|
676
|
-
return (value !== null && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype);
|
|
677
|
-
}
|
|
678
|
-
function mergeConfig(base, override) {
|
|
679
|
-
if (override == null) {
|
|
680
|
-
return structuredClone(base);
|
|
681
|
-
}
|
|
682
|
-
return merge(base, override);
|
|
683
|
-
}
|
|
684
|
-
function merge(base, override) {
|
|
685
|
-
if (override === undefined) {
|
|
686
|
-
return base;
|
|
687
|
-
}
|
|
688
|
-
if (base === undefined) {
|
|
689
|
-
return override;
|
|
690
|
-
}
|
|
691
|
-
if (Array.isArray(base) && Array.isArray(override)) {
|
|
692
|
-
return [...override];
|
|
693
|
-
}
|
|
694
|
-
if (isPlainObject(base) && isPlainObject(override)) {
|
|
695
|
-
const result = {};
|
|
696
|
-
const keys = new Set([...Object.keys(base), ...Object.keys(override)]);
|
|
697
|
-
for (const key of keys) {
|
|
698
|
-
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
|
|
699
|
-
continue;
|
|
700
|
-
}
|
|
701
|
-
result[key] = merge(base[key], override[key]);
|
|
702
|
-
}
|
|
703
|
-
return result;
|
|
704
|
-
}
|
|
705
|
-
// Primitive / Function / Class / Date / RegExp ...
|
|
706
|
-
return override;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
675
|
const WINDOW = new InjectionToken('WINDOW', {
|
|
710
676
|
factory: () => (typeof window !== 'undefined' ? window : null),
|
|
711
677
|
});
|
|
@@ -802,6 +768,331 @@ function mergeDeep(...objects) {
|
|
|
802
768
|
}, {});
|
|
803
769
|
}
|
|
804
770
|
|
|
771
|
+
/**
|
|
772
|
+
* Filters a hierarchical tree while preserving the branches
|
|
773
|
+
* that contain matching nodes.
|
|
774
|
+
*
|
|
775
|
+
* A node is included when:
|
|
776
|
+
* - the filter function matches the node itself, or
|
|
777
|
+
* - one or more of its descendants match.
|
|
778
|
+
*
|
|
779
|
+
* When only a descendant matches, a shallow copy of the parent
|
|
780
|
+
* is returned with only the matching descendants preserved.
|
|
781
|
+
*
|
|
782
|
+
* @param data The tree nodes to filter.
|
|
783
|
+
* @param filterFn Function used to determine whether a node matches.
|
|
784
|
+
* @param options Optional filtering configuration.
|
|
785
|
+
*
|
|
786
|
+
* @example
|
|
787
|
+
* ```ts
|
|
788
|
+
* const result = filterTreeList(
|
|
789
|
+
* dataTree,
|
|
790
|
+
* item =>
|
|
791
|
+
* item.name.toLowerCase().includes(filter) ||
|
|
792
|
+
* item.type.toLowerCase().includes(filter),
|
|
793
|
+
* );
|
|
794
|
+
* ```
|
|
795
|
+
*
|
|
796
|
+
* @example
|
|
797
|
+
* ```ts
|
|
798
|
+
* const result = filterTreeList(
|
|
799
|
+
* data,
|
|
800
|
+
* item => item.title.includes('angular'),
|
|
801
|
+
* { childrenKeyName: 'items' },
|
|
802
|
+
* );
|
|
803
|
+
* ```
|
|
804
|
+
*/
|
|
805
|
+
function filterTreeList(data, filterFn, options) {
|
|
806
|
+
if (!data?.length) {
|
|
807
|
+
return [];
|
|
808
|
+
}
|
|
809
|
+
const childrenKeyName = options?.childrenKeyName ?? 'children';
|
|
810
|
+
return filterNodes(data, filterFn, childrenKeyName);
|
|
811
|
+
}
|
|
812
|
+
function filterNodes(nodes, filterFn, childrenKeyName) {
|
|
813
|
+
const result = [];
|
|
814
|
+
for (const node of nodes) {
|
|
815
|
+
if (filterFn(node)) {
|
|
816
|
+
result.push(node);
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
const children = node[childrenKeyName];
|
|
820
|
+
if (!Array.isArray(children) || children.length === 0) {
|
|
821
|
+
continue;
|
|
822
|
+
}
|
|
823
|
+
const filteredChildren = filterNodes(children, filterFn, childrenKeyName);
|
|
824
|
+
if (filteredChildren.length > 0) {
|
|
825
|
+
result.push({
|
|
826
|
+
...node,
|
|
827
|
+
[childrenKeyName]: filteredChildren,
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
return result;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
const COLOR_FUNCTION_REGEX = /\b(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)\(\s*[^)]*\)/gi;
|
|
835
|
+
const HEX_COLOR_REGEX = /#[a-f\d]{3,4}(?:[a-f\d]{2}){0,2}\b/gi;
|
|
836
|
+
/**
|
|
837
|
+
* CSS named colors.
|
|
838
|
+
*
|
|
839
|
+
* Includes all standard CSS color keywords plus:
|
|
840
|
+
* - transparent
|
|
841
|
+
* - currentcolor
|
|
842
|
+
*/
|
|
843
|
+
const CSS_COLOR_NAMES = {
|
|
844
|
+
aliceblue: '#f0f8ff',
|
|
845
|
+
antiquewhite: '#faebd7',
|
|
846
|
+
aqua: '#00ffff',
|
|
847
|
+
aquamarine: '#7fffd4',
|
|
848
|
+
azure: '#f0ffff',
|
|
849
|
+
beige: '#f5f5dc',
|
|
850
|
+
bisque: '#ffe4c4',
|
|
851
|
+
black: '#000000',
|
|
852
|
+
blanchedalmond: '#ffebcd',
|
|
853
|
+
blue: '#0000ff',
|
|
854
|
+
blueviolet: '#8a2be2',
|
|
855
|
+
brown: '#a52a2a',
|
|
856
|
+
burlywood: '#deb887',
|
|
857
|
+
cadetblue: '#5f9ea0',
|
|
858
|
+
chartreuse: '#7fff00',
|
|
859
|
+
chocolate: '#d2691e',
|
|
860
|
+
coral: '#ff7f50',
|
|
861
|
+
cornflowerblue: '#6495ed',
|
|
862
|
+
cornsilk: '#fff8dc',
|
|
863
|
+
crimson: '#dc143c',
|
|
864
|
+
cyan: '#00ffff',
|
|
865
|
+
darkblue: '#00008b',
|
|
866
|
+
darkcyan: '#008b8b',
|
|
867
|
+
darkgoldenrod: '#b8860b',
|
|
868
|
+
darkgray: '#a9a9a9',
|
|
869
|
+
darkgreen: '#006400',
|
|
870
|
+
darkgrey: '#a9a9a9',
|
|
871
|
+
darkkhaki: '#bdb76b',
|
|
872
|
+
darkmagenta: '#8b008b',
|
|
873
|
+
darkolivegreen: '#556b2f',
|
|
874
|
+
darkorange: '#ff8c00',
|
|
875
|
+
darkorchid: '#9932cc',
|
|
876
|
+
darkred: '#8b0000',
|
|
877
|
+
darksalmon: '#e9967a',
|
|
878
|
+
darkseagreen: '#8fbc8f',
|
|
879
|
+
darkslateblue: '#483d8b',
|
|
880
|
+
darkslategray: '#2f4f4f',
|
|
881
|
+
darkslategrey: '#2f4f4f',
|
|
882
|
+
darkturquoise: '#00ced1',
|
|
883
|
+
darkviolet: '#9400d3',
|
|
884
|
+
deeppink: '#ff1493',
|
|
885
|
+
deepskyblue: '#00bfff',
|
|
886
|
+
dimgray: '#696969',
|
|
887
|
+
dimgrey: '#696969',
|
|
888
|
+
dodgerblue: '#1e90ff',
|
|
889
|
+
firebrick: '#b22222',
|
|
890
|
+
floralwhite: '#fffaf0',
|
|
891
|
+
forestgreen: '#228b22',
|
|
892
|
+
fuchsia: '#ff00ff',
|
|
893
|
+
gainsboro: '#dcdcdc',
|
|
894
|
+
ghostwhite: '#f8f8ff',
|
|
895
|
+
gold: '#ffd700',
|
|
896
|
+
goldenrod: '#daa520',
|
|
897
|
+
gray: '#808080',
|
|
898
|
+
green: '#008000',
|
|
899
|
+
greenyellow: '#adff2f',
|
|
900
|
+
grey: '#808080',
|
|
901
|
+
honeydew: '#f0fff0',
|
|
902
|
+
hotpink: '#ff69b4',
|
|
903
|
+
indianred: '#cd5c5c',
|
|
904
|
+
indigo: '#4b0082',
|
|
905
|
+
ivory: '#fffff0',
|
|
906
|
+
khaki: '#f0e68c',
|
|
907
|
+
lavender: '#e6e6fa',
|
|
908
|
+
lavenderblush: '#fff0f5',
|
|
909
|
+
lawngreen: '#7cfc00',
|
|
910
|
+
lemonchiffon: '#fffacd',
|
|
911
|
+
lightblue: '#add8e6',
|
|
912
|
+
lightcoral: '#f08080',
|
|
913
|
+
lightcyan: '#e0ffff',
|
|
914
|
+
lightgoldenrodyellow: '#fafad2',
|
|
915
|
+
lightgray: '#d3d3d3',
|
|
916
|
+
lightgreen: '#90ee90',
|
|
917
|
+
lightgrey: '#d3d3d3',
|
|
918
|
+
lightpink: '#ffb6c1',
|
|
919
|
+
lightsalmon: '#ffa07a',
|
|
920
|
+
lightseagreen: '#20b2aa',
|
|
921
|
+
lightskyblue: '#87cefa',
|
|
922
|
+
lightslategray: '#778899',
|
|
923
|
+
lightslategrey: '#778899',
|
|
924
|
+
lightsteelblue: '#b0c4de',
|
|
925
|
+
lightyellow: '#ffffe0',
|
|
926
|
+
lime: '#00ff00',
|
|
927
|
+
limegreen: '#32cd32',
|
|
928
|
+
linen: '#faf0e6',
|
|
929
|
+
magenta: '#ff00ff',
|
|
930
|
+
maroon: '#800000',
|
|
931
|
+
mediumaquamarine: '#66cdaa',
|
|
932
|
+
mediumblue: '#0000cd',
|
|
933
|
+
mediumorchid: '#ba55d3',
|
|
934
|
+
mediumpurple: '#9370db',
|
|
935
|
+
mediumseagreen: '#3cb371',
|
|
936
|
+
mediumslateblue: '#7b68ee',
|
|
937
|
+
mediumspringgreen: '#00fa9a',
|
|
938
|
+
mediumturquoise: '#48d1cc',
|
|
939
|
+
mediumvioletred: '#c71585',
|
|
940
|
+
midnightblue: '#191970',
|
|
941
|
+
mintcream: '#f5fffa',
|
|
942
|
+
mistyrose: '#ffe4e1',
|
|
943
|
+
moccasin: '#ffe4b5',
|
|
944
|
+
navajowhite: '#ffdead',
|
|
945
|
+
navy: '#000080',
|
|
946
|
+
oldlace: '#fdf5e6',
|
|
947
|
+
olive: '#808000',
|
|
948
|
+
olivedrab: '#6b8e23',
|
|
949
|
+
orange: '#ffa500',
|
|
950
|
+
orangered: '#ff4500',
|
|
951
|
+
orchid: '#da70d6',
|
|
952
|
+
palegoldenrod: '#eee8aa',
|
|
953
|
+
palegreen: '#98fb98',
|
|
954
|
+
paleturquoise: '#afeeee',
|
|
955
|
+
palevioletred: '#db7093',
|
|
956
|
+
papayawhip: '#ffefd5',
|
|
957
|
+
peachpuff: '#ffdab9',
|
|
958
|
+
peru: '#cd853f',
|
|
959
|
+
pink: '#ffc0cb',
|
|
960
|
+
plum: '#dda0dd',
|
|
961
|
+
powderblue: '#b0e0e6',
|
|
962
|
+
purple: '#800080',
|
|
963
|
+
rebeccapurple: '#663399',
|
|
964
|
+
red: '#ff0000',
|
|
965
|
+
rosybrown: '#bc8f8f',
|
|
966
|
+
royalblue: '#4169e1',
|
|
967
|
+
saddlebrown: '#8b4513',
|
|
968
|
+
salmon: '#fa8072',
|
|
969
|
+
sandybrown: '#f4a460',
|
|
970
|
+
seagreen: '#2e8b57',
|
|
971
|
+
seashell: '#fff5ee',
|
|
972
|
+
sienna: '#a0522d',
|
|
973
|
+
silver: '#c0c0c0',
|
|
974
|
+
skyblue: '#87ceeb',
|
|
975
|
+
slateblue: '#6a5acd',
|
|
976
|
+
slategray: '#708090',
|
|
977
|
+
slategrey: '#708090',
|
|
978
|
+
snow: '#fffafa',
|
|
979
|
+
springgreen: '#00ff7f',
|
|
980
|
+
steelblue: '#4682b4',
|
|
981
|
+
tan: '#d2b48c',
|
|
982
|
+
teal: '#008080',
|
|
983
|
+
thistle: '#d8bfd8',
|
|
984
|
+
tomato: '#ff6347',
|
|
985
|
+
turquoise: '#40e0d0',
|
|
986
|
+
violet: '#ee82ee',
|
|
987
|
+
wheat: '#f5deb3',
|
|
988
|
+
white: '#ffffff',
|
|
989
|
+
whitesmoke: '#f5f5f5',
|
|
990
|
+
yellow: '#ffff00',
|
|
991
|
+
yellowgreen: '#9acd32',
|
|
992
|
+
};
|
|
993
|
+
/**
|
|
994
|
+
* Extract all CSS colors from an arbitrary CSS string.
|
|
995
|
+
*
|
|
996
|
+
* Supports:
|
|
997
|
+
* - Hex: #fff, #ffff, #ffffff, #ffffffff
|
|
998
|
+
* - rgb()
|
|
999
|
+
* - rgba()
|
|
1000
|
+
* - hsl()
|
|
1001
|
+
* - hsla()
|
|
1002
|
+
* - hwb()
|
|
1003
|
+
* - lab()
|
|
1004
|
+
* - lch()
|
|
1005
|
+
* - oklab()
|
|
1006
|
+
* - oklch()
|
|
1007
|
+
* - color()
|
|
1008
|
+
* - CSS named colors
|
|
1009
|
+
* - transparent
|
|
1010
|
+
* - currentcolor
|
|
1011
|
+
*
|
|
1012
|
+
* Works with values such as:
|
|
1013
|
+
*
|
|
1014
|
+
* box-shadow: 0 0 10px red, 0 0 20px #00ff00;
|
|
1015
|
+
* linear-gradient(red, rgba(0, 0, 0, .5));
|
|
1016
|
+
* radial-gradient(circle, blue 0%, transparent 100%);
|
|
1017
|
+
* conic-gradient(from 90deg, yellow, #ff0000);
|
|
1018
|
+
*/
|
|
1019
|
+
function extractCssColors(value) {
|
|
1020
|
+
if (!value) {
|
|
1021
|
+
return [];
|
|
1022
|
+
}
|
|
1023
|
+
const colors = [];
|
|
1024
|
+
const seen = new Set();
|
|
1025
|
+
const addColor = (color) => {
|
|
1026
|
+
const normalized = color.trim();
|
|
1027
|
+
if (!normalized) {
|
|
1028
|
+
return;
|
|
1029
|
+
}
|
|
1030
|
+
const key = normalized.toLowerCase();
|
|
1031
|
+
if (seen.has(key)) {
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
seen.add(key);
|
|
1035
|
+
colors.push(normalized);
|
|
1036
|
+
};
|
|
1037
|
+
// ---------------------------------------------------------
|
|
1038
|
+
// 1. Hex colors
|
|
1039
|
+
// ---------------------------------------------------------
|
|
1040
|
+
for (const match of value.matchAll(HEX_COLOR_REGEX)) {
|
|
1041
|
+
addColor(match[0]);
|
|
1042
|
+
}
|
|
1043
|
+
// ---------------------------------------------------------
|
|
1044
|
+
// 2. CSS color functions
|
|
1045
|
+
// ---------------------------------------------------------
|
|
1046
|
+
for (const match of value.matchAll(COLOR_FUNCTION_REGEX)) {
|
|
1047
|
+
const candidate = match[0];
|
|
1048
|
+
if (isValidCssColor(candidate)) {
|
|
1049
|
+
addColor(candidate);
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
// ---------------------------------------------------------
|
|
1053
|
+
// 3. Named colors
|
|
1054
|
+
// ---------------------------------------------------------
|
|
1055
|
+
/**
|
|
1056
|
+
* We intentionally extract words instead of putting all named
|
|
1057
|
+
* colors into one huge regex.
|
|
1058
|
+
*/
|
|
1059
|
+
const words = value.match(/\b[a-z][a-z0-9-]*\b/gi) ?? [];
|
|
1060
|
+
for (const word of words) {
|
|
1061
|
+
const normalized = word.toLowerCase();
|
|
1062
|
+
if (!CSS_COLOR_NAMES[normalized]) {
|
|
1063
|
+
continue;
|
|
1064
|
+
}
|
|
1065
|
+
if (isValidCssColor(word)) {
|
|
1066
|
+
addColor(word);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
return colors;
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Uses the browser's CSS parser to validate a color.
|
|
1073
|
+
*
|
|
1074
|
+
* This is much safer than trying to validate every possible
|
|
1075
|
+
* CSS color syntax manually.
|
|
1076
|
+
*/
|
|
1077
|
+
function isValidCssColor(value) {
|
|
1078
|
+
if (typeof CSS !== 'undefined' && typeof CSS.supports === 'function') {
|
|
1079
|
+
return CSS.supports('color', value);
|
|
1080
|
+
}
|
|
1081
|
+
// SSR / Node fallback.
|
|
1082
|
+
return isFallbackCssColor(value);
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Minimal validation for environments without CSS.supports(),
|
|
1086
|
+
* such as SSR or Node tests.
|
|
1087
|
+
*/
|
|
1088
|
+
function isFallbackCssColor(value) {
|
|
1089
|
+
const normalized = value.trim().toLowerCase();
|
|
1090
|
+
if (CSS_COLOR_NAMES[normalized]) {
|
|
1091
|
+
return true;
|
|
1092
|
+
}
|
|
1093
|
+
return /^#[a-f\d]{3,4}(?:[a-f\d]{2}){0,2}$/i.test(normalized);
|
|
1094
|
+
}
|
|
1095
|
+
|
|
805
1096
|
class BrowserService {
|
|
806
1097
|
platformId;
|
|
807
1098
|
constructor(platformId) {
|
|
@@ -885,341 +1176,681 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImpor
|
|
|
885
1176
|
}], ctorParameters: () => [] });
|
|
886
1177
|
|
|
887
1178
|
class OverlayRef {
|
|
888
|
-
|
|
889
|
-
|
|
1179
|
+
element;
|
|
1180
|
+
closeFn;
|
|
890
1181
|
componentRef;
|
|
891
|
-
|
|
892
|
-
constructor(
|
|
893
|
-
this.
|
|
894
|
-
this.
|
|
1182
|
+
template;
|
|
1183
|
+
constructor(element, closeFn, componentRef, template) {
|
|
1184
|
+
this.element = element;
|
|
1185
|
+
this.closeFn = closeFn;
|
|
895
1186
|
this.componentRef = componentRef;
|
|
896
|
-
this.
|
|
1187
|
+
this.template = template;
|
|
897
1188
|
}
|
|
898
1189
|
close() {
|
|
899
|
-
this.
|
|
1190
|
+
this.closeFn();
|
|
900
1191
|
}
|
|
901
1192
|
get nativeElement() {
|
|
902
|
-
return this.
|
|
1193
|
+
return this.element;
|
|
1194
|
+
}
|
|
1195
|
+
static noop() {
|
|
1196
|
+
return new OverlayRef(null, () => { });
|
|
903
1197
|
}
|
|
904
1198
|
}
|
|
905
1199
|
|
|
906
|
-
const FOCUSABLE_SELECTOR =
|
|
1200
|
+
const FOCUSABLE_SELECTOR = [
|
|
1201
|
+
'button:not([disabled])',
|
|
1202
|
+
'[href]',
|
|
1203
|
+
'input:not([disabled])',
|
|
1204
|
+
'select:not([disabled])',
|
|
1205
|
+
'textarea:not([disabled])',
|
|
1206
|
+
'[tabindex]:not([tabindex="-1"])',
|
|
1207
|
+
].join(',');
|
|
907
1208
|
const DIALOG_OVERLAY_CLASSNAME = 'ngx-ui-overlay';
|
|
1209
|
+
const OVERLAY_HOST_CLASSNAME = 'ngx-ui-overlay-host';
|
|
1210
|
+
const BASE_Z_INDEX = 1000;
|
|
908
1211
|
class OverlayService {
|
|
909
|
-
|
|
910
|
-
listenersAttached = false;
|
|
911
|
-
resizeRafPending = false;
|
|
912
|
-
doc = inject(DOCUMENT);
|
|
913
|
-
abortController = new AbortController();
|
|
1212
|
+
document = inject(DOCUMENT);
|
|
914
1213
|
directionService = inject(DirectionService);
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
1214
|
+
platformId = inject(PLATFORM_ID);
|
|
1215
|
+
applicationRef = inject(ApplicationRef);
|
|
1216
|
+
environmentInjector = inject(EnvironmentInjector);
|
|
1217
|
+
overlayStack = [];
|
|
1218
|
+
globalListenersAttached = false;
|
|
1219
|
+
layoutRaf = null;
|
|
1220
|
+
bodyScrollLockCount = 0;
|
|
1221
|
+
previousBodyOverflow = null;
|
|
1222
|
+
previousBodyPaddingRight = null;
|
|
1223
|
+
get isBrowser() {
|
|
1224
|
+
return isPlatformBrowser(this.platformId);
|
|
1225
|
+
}
|
|
1226
|
+
/** Number of overlays currently open. */
|
|
1227
|
+
get openCount() {
|
|
1228
|
+
return this.overlayStack.length;
|
|
918
1229
|
}
|
|
919
1230
|
open(options) {
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1231
|
+
if (!this.isBrowser) {
|
|
1232
|
+
return OverlayRef.noop();
|
|
1233
|
+
}
|
|
1234
|
+
const { component, viewContainerRef, configure, onClosed } = options;
|
|
1235
|
+
const instance = this.createComponentInstance(options, component, viewContainerRef);
|
|
1236
|
+
this.pushInstance(instance);
|
|
1237
|
+
this.renderHost(instance);
|
|
1238
|
+
this.attachGlobalListeners();
|
|
1239
|
+
instance.onClosed = onClosed;
|
|
1240
|
+
configure?.(instance.componentRef.instance, new OverlayRef(instance.element, instance.cleanup, instance.componentRef));
|
|
1241
|
+
this.scheduleInitialLayout(instance);
|
|
1242
|
+
return new OverlayRef(instance.element, instance.cleanup, instance.componentRef);
|
|
1243
|
+
}
|
|
1244
|
+
openTemplate(options) {
|
|
1245
|
+
if (!this.isBrowser) {
|
|
1246
|
+
return OverlayRef.noop();
|
|
923
1247
|
}
|
|
1248
|
+
const { template, appRef, configure, onClosed } = options;
|
|
1249
|
+
const instance = this.createTemplateInstance(options, template, appRef ?? this.applicationRef);
|
|
1250
|
+
this.pushInstance(instance);
|
|
1251
|
+
this.renderHost(instance);
|
|
924
1252
|
this.attachGlobalListeners();
|
|
925
|
-
|
|
926
|
-
const
|
|
927
|
-
|
|
928
|
-
|
|
1253
|
+
instance.onClosed = onClosed;
|
|
1254
|
+
const ref = new OverlayRef(instance.element, instance.cleanup, undefined, template);
|
|
1255
|
+
configure?.(instance, ref);
|
|
1256
|
+
this.scheduleInitialLayout(instance);
|
|
1257
|
+
return ref;
|
|
1258
|
+
}
|
|
1259
|
+
closeAll() {
|
|
1260
|
+
if (!this.isBrowser) {
|
|
1261
|
+
return;
|
|
1262
|
+
}
|
|
1263
|
+
[...this.overlayStack].forEach((instance) => {
|
|
1264
|
+
instance.cleanup();
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
// ---------------------------------------------------------------------------
|
|
1268
|
+
// instance creation
|
|
1269
|
+
// ---------------------------------------------------------------------------
|
|
1270
|
+
createComponentInstance(options, component, viewContainerRef) {
|
|
1271
|
+
const host = this.createHostElement(options);
|
|
1272
|
+
const backdrop = this.createBackdropElement(options);
|
|
1273
|
+
const element = this.createOverlayElement(options);
|
|
1274
|
+
host.appendChild(backdrop);
|
|
1275
|
+
host.appendChild(element);
|
|
1276
|
+
let componentRef;
|
|
1277
|
+
let attachedToAppRef = false;
|
|
1278
|
+
if (viewContainerRef) {
|
|
1279
|
+
componentRef = options.injector
|
|
1280
|
+
? viewContainerRef.createComponent(component, { injector: options.injector })
|
|
1281
|
+
: viewContainerRef.createComponent(component);
|
|
1282
|
+
}
|
|
1283
|
+
else {
|
|
1284
|
+
// No host ViewContainerRef available (e.g. a global service opening an
|
|
1285
|
+
// overlay outside of any component template) - create and attach the
|
|
1286
|
+
// component directly against the application, like a root component.
|
|
1287
|
+
componentRef = createComponent(component, {
|
|
1288
|
+
environmentInjector: this.environmentInjector,
|
|
1289
|
+
elementInjector: options.injector,
|
|
1290
|
+
});
|
|
1291
|
+
this.applicationRef.attachView(componentRef.hostView);
|
|
1292
|
+
attachedToAppRef = true;
|
|
929
1293
|
}
|
|
1294
|
+
element.appendChild(componentRef.location.nativeElement);
|
|
930
1295
|
const instance = {
|
|
1296
|
+
host,
|
|
1297
|
+
backdrop,
|
|
931
1298
|
element,
|
|
932
|
-
anchor,
|
|
933
|
-
point,
|
|
934
|
-
placementConfig: this.resolvePlacementConfig(placement, alignment, margin),
|
|
1299
|
+
anchor: options.anchor,
|
|
1300
|
+
point: options.point,
|
|
1301
|
+
placementConfig: this.resolvePlacementConfig(options.placement, options.alignment, options.margin),
|
|
1302
|
+
usePopover: this.resolveUsePopover(options),
|
|
1303
|
+
closeOnEscape: options.closeOnEscape ?? true,
|
|
1304
|
+
closeOnOutsideClick: options.closeOnOutsideClick ?? true,
|
|
1305
|
+
canClose: options.canClose,
|
|
1306
|
+
autoFocus: options.autoFocus ?? true,
|
|
1307
|
+
restoreFocus: options.restoreFocus ?? true,
|
|
1308
|
+
lockBodyScroll: options.lockBodyScroll ?? false,
|
|
935
1309
|
componentRef,
|
|
936
|
-
|
|
1310
|
+
attachedToAppRef,
|
|
1311
|
+
previousActiveElement: this.getActiveElement(),
|
|
937
1312
|
rafId: null,
|
|
938
1313
|
focusTimeoutId: null,
|
|
939
1314
|
cleanup: () => { },
|
|
940
1315
|
};
|
|
941
1316
|
instance.cleanup = () => this.destroyInstance(instance);
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
this.
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
const { anchor, point, template, appRef, configure, onClosed, placement, alignment, margin } = options;
|
|
951
|
-
this.attachGlobalListeners();
|
|
952
|
-
const element = this.createDialogElement();
|
|
1317
|
+
return instance;
|
|
1318
|
+
}
|
|
1319
|
+
createTemplateInstance(options, template, appRef) {
|
|
1320
|
+
const host = this.createHostElement(options);
|
|
1321
|
+
const backdrop = this.createBackdropElement(options);
|
|
1322
|
+
const element = this.createOverlayElement(options);
|
|
1323
|
+
host.appendChild(backdrop);
|
|
1324
|
+
host.appendChild(element);
|
|
953
1325
|
const view = template.createEmbeddedView({});
|
|
954
1326
|
appRef.attachView(view);
|
|
955
1327
|
element.append(...view.rootNodes);
|
|
956
1328
|
const instance = {
|
|
1329
|
+
host,
|
|
1330
|
+
backdrop,
|
|
957
1331
|
element,
|
|
958
|
-
anchor,
|
|
959
|
-
point,
|
|
960
|
-
placementConfig: this.resolvePlacementConfig(placement, alignment, margin),
|
|
1332
|
+
anchor: options.anchor,
|
|
1333
|
+
point: options.point,
|
|
1334
|
+
placementConfig: this.resolvePlacementConfig(options.placement, options.alignment, options.margin),
|
|
1335
|
+
usePopover: this.resolveUsePopover(options),
|
|
1336
|
+
closeOnEscape: options.closeOnEscape ?? true,
|
|
1337
|
+
closeOnOutsideClick: options.closeOnOutsideClick ?? true,
|
|
1338
|
+
canClose: options.canClose,
|
|
1339
|
+
autoFocus: options.autoFocus ?? true,
|
|
1340
|
+
restoreFocus: options.restoreFocus ?? true,
|
|
1341
|
+
lockBodyScroll: options.lockBodyScroll ?? false,
|
|
961
1342
|
embeddedView: view,
|
|
962
1343
|
appRef,
|
|
963
|
-
|
|
1344
|
+
previousActiveElement: this.getActiveElement(),
|
|
964
1345
|
rafId: null,
|
|
965
1346
|
focusTimeoutId: null,
|
|
966
1347
|
cleanup: () => { },
|
|
967
1348
|
};
|
|
968
1349
|
instance.cleanup = () => this.destroyInstance(instance);
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
}
|
|
980
|
-
// ---------------------------------------------------------------------
|
|
981
|
-
// lifecycle
|
|
982
|
-
// ---------------------------------------------------------------------
|
|
983
|
-
resolvePlacementConfig(placement, alignment, margin) {
|
|
984
|
-
return {
|
|
985
|
-
placement: placement ?? 'auto',
|
|
986
|
-
alignment: alignment ?? 'start',
|
|
987
|
-
margin: margin ?? 8,
|
|
988
|
-
};
|
|
1350
|
+
return instance;
|
|
1351
|
+
}
|
|
1352
|
+
pushInstance(instance) {
|
|
1353
|
+
this.overlayStack.push(instance);
|
|
1354
|
+
// Only matters as a fallback for browsers without the Popover API -
|
|
1355
|
+
// real popovers stack by top-layer show order regardless of z-index.
|
|
1356
|
+
instance.host.style.zIndex = String(BASE_Z_INDEX + this.overlayStack.length);
|
|
1357
|
+
if (instance.lockBodyScroll) {
|
|
1358
|
+
this.lockBodyScroll();
|
|
1359
|
+
}
|
|
989
1360
|
}
|
|
990
|
-
|
|
991
|
-
|
|
1361
|
+
// ---------------------------------------------------------------------------
|
|
1362
|
+
// DOM
|
|
1363
|
+
// ---------------------------------------------------------------------------
|
|
1364
|
+
createHostElement(options) {
|
|
1365
|
+
const usePopover = this.resolveUsePopover(options);
|
|
1366
|
+
const host = this.document.createElement('div');
|
|
1367
|
+
host.className = OVERLAY_HOST_CLASSNAME;
|
|
1368
|
+
host.setAttribute('data-ngx-overlay', '');
|
|
1369
|
+
host.style.position = 'fixed';
|
|
1370
|
+
host.style.inset = '0';
|
|
1371
|
+
// Neutralize the browser's default `[popover]` UA stylesheet
|
|
1372
|
+
// (margin: auto; width/height: fit-content; border: solid; padding: .25em;
|
|
1373
|
+
// background: Canvas; overflow: auto) so the host reliably fills the
|
|
1374
|
+
// viewport whether or not it ends up being a real popover.
|
|
1375
|
+
host.style.margin = '0';
|
|
1376
|
+
host.style.padding = '0';
|
|
1377
|
+
host.style.border = 'none';
|
|
1378
|
+
host.style.width = '100%';
|
|
1379
|
+
host.style.height = '100%';
|
|
1380
|
+
host.style.maxWidth = 'none';
|
|
1381
|
+
host.style.maxHeight = 'none';
|
|
1382
|
+
host.style.overflow = 'visible';
|
|
1383
|
+
host.style.background = 'transparent';
|
|
1384
|
+
host.style.color = 'inherit';
|
|
1385
|
+
host.style.zIndex = String(BASE_Z_INDEX);
|
|
1386
|
+
host.style.pointerEvents = 'auto';
|
|
1387
|
+
// Popover goes on the ROOT element, not the inner panel. This puts the
|
|
1388
|
+
// whole overlay (backdrop + panel) in the top layer as a single unit,
|
|
1389
|
+
// so stacking "just works" above everything on the page - including
|
|
1390
|
+
// ancestors with `overflow: hidden`, `transform`, or their own z-index
|
|
1391
|
+
// stacking contexts, which regular `position: fixed` cannot escape.
|
|
1392
|
+
// The inner `element` stays a normal `position: fixed` div and keeps
|
|
1393
|
+
// computing against the viewport, so all the placement math is unchanged.
|
|
1394
|
+
if (usePopover) {
|
|
1395
|
+
host.setAttribute('popover', 'manual');
|
|
1396
|
+
}
|
|
1397
|
+
return host;
|
|
1398
|
+
}
|
|
1399
|
+
createBackdropElement(options) {
|
|
1400
|
+
const backdrop = this.document.createElement('div');
|
|
1401
|
+
backdrop.className = 'ngx-ui-overlay-backdrop';
|
|
1402
|
+
backdrop.style.position = 'absolute';
|
|
1403
|
+
backdrop.style.inset = '0';
|
|
1404
|
+
backdrop.style.pointerEvents = 'auto';
|
|
1405
|
+
backdrop.style.background = 'transparent';
|
|
1406
|
+
this.addClasses(backdrop, options.backdropClass);
|
|
1407
|
+
return backdrop;
|
|
1408
|
+
}
|
|
1409
|
+
createOverlayElement(options) {
|
|
1410
|
+
const element = this.document.createElement('div');
|
|
992
1411
|
element.className = DIALOG_OVERLAY_CLASSNAME;
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1412
|
+
element.setAttribute('role', options.role ?? 'dialog');
|
|
1413
|
+
if (options.ariaModal ?? true) {
|
|
1414
|
+
element.setAttribute('aria-modal', 'true');
|
|
1415
|
+
}
|
|
1416
|
+
if (options.ariaLabel) {
|
|
1417
|
+
element.setAttribute('aria-label', options.ariaLabel);
|
|
1418
|
+
}
|
|
1419
|
+
if (options.ariaLabelledby) {
|
|
1420
|
+
element.setAttribute('aria-labelledby', options.ariaLabelledby);
|
|
1421
|
+
}
|
|
1422
|
+
if (options.ariaDescribedby) {
|
|
1423
|
+
element.setAttribute('aria-describedby', options.ariaDescribedby);
|
|
1424
|
+
}
|
|
1425
|
+
element.setAttribute('tabindex', '-1');
|
|
1426
|
+
element.style.position = 'fixed';
|
|
1427
|
+
element.style.pointerEvents = 'auto';
|
|
1428
|
+
element.style.boxSizing = 'border-box';
|
|
1429
|
+
element.style.maxWidth = '100dvw'; // 'calc(100vw - 16px)';
|
|
1430
|
+
element.style.maxHeight = '100dvh'; // 'calc(100vh - 16px)';
|
|
1431
|
+
element.style.outline = 'none';
|
|
1432
|
+
element.style.border = 'none';
|
|
1433
|
+
element.style.padding = '0';
|
|
1434
|
+
element.style.margin = '0';
|
|
1435
|
+
element.style.overflow = 'auto';
|
|
1436
|
+
element.style.transformOrigin = 'left top';
|
|
1437
|
+
element.style.background = 'none';
|
|
1438
|
+
element.style.boxShadow = '0 0 20px light-dark(#79797955, #020202bd)';
|
|
1439
|
+
element.style.borderRadius = 'var(--ngx-dialog-corner-radius,1rem)';
|
|
1440
|
+
this.addClasses(element, options.panelClass);
|
|
1005
1441
|
return element;
|
|
1006
1442
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
}
|
|
1443
|
+
addClasses(element, classes) {
|
|
1444
|
+
if (!classes) {
|
|
1445
|
+
return;
|
|
1446
|
+
}
|
|
1447
|
+
const list = Array.isArray(classes) ? classes : classes.split(' ');
|
|
1448
|
+
for (const c of list) {
|
|
1449
|
+
if (c.trim()) {
|
|
1450
|
+
element.classList.add(c.trim());
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1017
1453
|
}
|
|
1454
|
+
renderHost(instance) {
|
|
1455
|
+
this.document.body.appendChild(instance.host);
|
|
1456
|
+
// Must show the popover (enter the top layer) BEFORE we ever measure
|
|
1457
|
+
// `instance.element`'s rect - while a popover host is closed it's
|
|
1458
|
+
// `display: none`, and everything inside it (including the panel)
|
|
1459
|
+
// would measure as a 0x0 box.
|
|
1460
|
+
this.showHostPopover(instance);
|
|
1461
|
+
instance.element.style.visibility = 'hidden';
|
|
1462
|
+
instance.element.style.position = 'fixed';
|
|
1463
|
+
instance.element.style.top = '0';
|
|
1464
|
+
instance.element.style.left = '0';
|
|
1465
|
+
}
|
|
1466
|
+
// ---------------------------------------------------------------------------
|
|
1467
|
+
// lifecycle
|
|
1468
|
+
// ---------------------------------------------------------------------------
|
|
1018
1469
|
destroyInstance(instance) {
|
|
1019
|
-
const index = this.
|
|
1020
|
-
if (index === -1)
|
|
1021
|
-
return;
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
if (instance.rafId !== null)
|
|
1025
|
-
cancelAnimationFrame(instance.rafId);
|
|
1026
|
-
|
|
1470
|
+
const index = this.overlayStack.indexOf(instance);
|
|
1471
|
+
if (index === -1) {
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
this.overlayStack.splice(index, 1);
|
|
1475
|
+
if (instance.rafId !== null) {
|
|
1476
|
+
this.cancelAnimationFrame(instance.rafId);
|
|
1477
|
+
instance.rafId = null;
|
|
1478
|
+
}
|
|
1479
|
+
if (instance.focusTimeoutId !== null) {
|
|
1027
1480
|
clearTimeout(instance.focusTimeoutId);
|
|
1481
|
+
instance.focusTimeoutId = null;
|
|
1482
|
+
}
|
|
1028
1483
|
if (instance.componentRef) {
|
|
1029
|
-
instance.
|
|
1484
|
+
if (instance.attachedToAppRef) {
|
|
1485
|
+
this.applicationRef.detachView(instance.componentRef.hostView);
|
|
1486
|
+
}
|
|
1030
1487
|
instance.componentRef.destroy();
|
|
1488
|
+
instance.componentRef = undefined;
|
|
1031
1489
|
}
|
|
1032
1490
|
if (instance.embeddedView && instance.appRef) {
|
|
1033
1491
|
instance.appRef.detachView(instance.embeddedView);
|
|
1034
1492
|
instance.embeddedView.destroy();
|
|
1493
|
+
instance.embeddedView = undefined;
|
|
1494
|
+
}
|
|
1495
|
+
this.hideHostPopover(instance);
|
|
1496
|
+
instance.host.remove();
|
|
1497
|
+
if (instance.lockBodyScroll) {
|
|
1498
|
+
this.unlockBodyScroll();
|
|
1499
|
+
}
|
|
1500
|
+
instance.onClosed?.();
|
|
1501
|
+
// Only tear down the shared/global listeners once *every* overlay is
|
|
1502
|
+
// closed - previously this ran unconditionally on every close, which
|
|
1503
|
+
// silently broke Escape/outside-click/reposition for any overlays that
|
|
1504
|
+
// were still open underneath.
|
|
1505
|
+
if (this.overlayStack.length === 0) {
|
|
1506
|
+
this.detachGlobalListeners();
|
|
1507
|
+
}
|
|
1508
|
+
if (instance.restoreFocus) {
|
|
1509
|
+
this.restoreFocus(instance.previousActiveElement);
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
// ---------------------------------------------------------------------------
|
|
1513
|
+
// popover helpers
|
|
1514
|
+
// ---------------------------------------------------------------------------
|
|
1515
|
+
resolveUsePopover(options) {
|
|
1516
|
+
return (options.usePopover ?? true) && this.supportsPopover();
|
|
1517
|
+
}
|
|
1518
|
+
showHostPopover(instance) {
|
|
1519
|
+
if (!instance.usePopover) {
|
|
1520
|
+
return;
|
|
1035
1521
|
}
|
|
1036
|
-
// قبل از remove()، دیالوگ رو با متد استاندارد close() میبندیم؛ این کار دو
|
|
1037
|
-
// فایده داره که با remove() ساده به دست نمیاومدن:
|
|
1038
|
-
// ۱) فوکوس بهصورت خودکار به همون المنتی که قبل از باز شدن دیالوگ فوکوس
|
|
1039
|
-
// داشت برمیگرده (رفتار استاندارد close() روی <dialog>) — با remove()
|
|
1040
|
-
// ساده این اتفاق نمیافته و فوکوس معمولاً روی body گم میشه.
|
|
1041
|
-
// ۲) رویداد 'close' استاندارد شلیک میشه، برای کدی که ممکنه به اون گوش بده.
|
|
1042
|
-
// در try/catch گذاشتیمش چون در محیط تست (jsdom) این متدها mock هستن و ممکنه
|
|
1043
|
-
// رفتار متفاوتی داشته باشن.
|
|
1044
1522
|
try {
|
|
1045
|
-
|
|
1046
|
-
instance.element.close();
|
|
1523
|
+
instance.host.showPopover();
|
|
1047
1524
|
}
|
|
1048
1525
|
catch {
|
|
1049
|
-
|
|
1526
|
+
// Already open, or environment doesn't fully support it - ignore.
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
hideHostPopover(instance) {
|
|
1530
|
+
if (!instance.usePopover) {
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
try {
|
|
1534
|
+
if (instance.host.matches(':popover-open')) {
|
|
1535
|
+
instance.host.hidePopover();
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
catch {
|
|
1539
|
+
// Not open, or already removed from the DOM - ignore.
|
|
1050
1540
|
}
|
|
1051
|
-
instance.element.remove();
|
|
1052
|
-
instance.onClosed?.();
|
|
1053
1541
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1542
|
+
supportsPopover() {
|
|
1543
|
+
return (typeof HTMLElement !== 'undefined' &&
|
|
1544
|
+
'popover' in HTMLElement.prototype &&
|
|
1545
|
+
typeof HTMLElement.prototype.showPopover === 'function' &&
|
|
1546
|
+
typeof HTMLElement.prototype.hidePopover === 'function');
|
|
1547
|
+
}
|
|
1548
|
+
// ---------------------------------------------------------------------------
|
|
1549
|
+
// body scroll lock
|
|
1550
|
+
// ---------------------------------------------------------------------------
|
|
1551
|
+
lockBodyScroll() {
|
|
1552
|
+
this.bodyScrollLockCount++;
|
|
1553
|
+
if (this.bodyScrollLockCount > 1) {
|
|
1554
|
+
return;
|
|
1555
|
+
}
|
|
1556
|
+
const body = this.document.body;
|
|
1557
|
+
this.previousBodyOverflow = body.style.overflow;
|
|
1558
|
+
this.previousBodyPaddingRight = body.style.paddingRight;
|
|
1559
|
+
const scrollbarWidth = window.innerWidth - this.document.documentElement.clientWidth;
|
|
1560
|
+
body.style.overflow = 'hidden';
|
|
1561
|
+
if (scrollbarWidth > 0) {
|
|
1562
|
+
const currentPaddingRight = parseFloat(window.getComputedStyle(body).paddingRight) || 0;
|
|
1563
|
+
body.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px`;
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
unlockBodyScroll() {
|
|
1567
|
+
if (this.bodyScrollLockCount === 0) {
|
|
1568
|
+
return;
|
|
1569
|
+
}
|
|
1570
|
+
this.bodyScrollLockCount--;
|
|
1571
|
+
if (this.bodyScrollLockCount > 0) {
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
const body = this.document.body;
|
|
1575
|
+
body.style.overflow = this.previousBodyOverflow ?? '';
|
|
1576
|
+
body.style.paddingRight = this.previousBodyPaddingRight ?? '';
|
|
1577
|
+
this.previousBodyOverflow = null;
|
|
1578
|
+
this.previousBodyPaddingRight = null;
|
|
1579
|
+
}
|
|
1580
|
+
// ---------------------------------------------------------------------------
|
|
1581
|
+
// global listeners
|
|
1582
|
+
// ---------------------------------------------------------------------------
|
|
1057
1583
|
attachGlobalListeners() {
|
|
1058
|
-
if (this.
|
|
1584
|
+
if (!this.isBrowser || this.globalListenersAttached) {
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
// Flip the flag synchronously to avoid a race: if two overlays open in
|
|
1588
|
+
// the same tick, the second call must see the flag already set instead
|
|
1589
|
+
// of scheduling a second (duplicate) round of addEventListener calls.
|
|
1590
|
+
this.globalListenersAttached = true;
|
|
1591
|
+
setTimeout(() => {
|
|
1592
|
+
this.document.addEventListener('keydown', this.onDocumentKeydown);
|
|
1593
|
+
this.document.addEventListener('click', this.onDocumentClick);
|
|
1594
|
+
this.document.addEventListener('contextmenu', this.onDocumentContextMenu);
|
|
1595
|
+
this.document.addEventListener('scroll', this.onDocumentScroll, true);
|
|
1596
|
+
window.addEventListener('resize', this.onWindowResize);
|
|
1597
|
+
}, 0);
|
|
1598
|
+
}
|
|
1599
|
+
detachGlobalListeners() {
|
|
1600
|
+
if (!this.isBrowser || !this.globalListenersAttached) {
|
|
1059
1601
|
return;
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
this.
|
|
1063
|
-
|
|
1064
|
-
this.
|
|
1065
|
-
this.
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1602
|
+
}
|
|
1603
|
+
this.globalListenersAttached = false;
|
|
1604
|
+
this.document.removeEventListener('keydown', this.onDocumentKeydown);
|
|
1605
|
+
this.document.removeEventListener('click', this.onDocumentClick);
|
|
1606
|
+
this.document.removeEventListener('contextmenu', this.onDocumentContextMenu);
|
|
1607
|
+
this.document.removeEventListener('scroll', this.onDocumentScroll, true);
|
|
1608
|
+
window.removeEventListener('resize', this.onWindowResize);
|
|
1609
|
+
}
|
|
1610
|
+
onDocumentKeydown = (event) => {
|
|
1611
|
+
const instance = this.getLastInstance();
|
|
1612
|
+
if (!instance) {
|
|
1069
1613
|
return;
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1614
|
+
}
|
|
1615
|
+
if (event.key === 'Escape') {
|
|
1616
|
+
if (!instance.closeOnEscape || (instance.canClose && !instance.canClose())) {
|
|
1617
|
+
return;
|
|
1618
|
+
}
|
|
1619
|
+
event.preventDefault();
|
|
1620
|
+
instance.cleanup();
|
|
1075
1621
|
return;
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
this.
|
|
1079
|
-
|
|
1080
|
-
});
|
|
1622
|
+
}
|
|
1623
|
+
if (event.key === 'Tab') {
|
|
1624
|
+
this.trapFocus(event, instance);
|
|
1625
|
+
}
|
|
1081
1626
|
};
|
|
1082
|
-
|
|
1083
|
-
this.
|
|
1627
|
+
onDocumentClick = (event) => {
|
|
1628
|
+
const instance = this.getLastInstance();
|
|
1629
|
+
if (!instance) {
|
|
1630
|
+
return;
|
|
1631
|
+
}
|
|
1632
|
+
const target = event.target;
|
|
1633
|
+
if (!target) {
|
|
1634
|
+
return;
|
|
1635
|
+
}
|
|
1636
|
+
if (instance.element.contains(target)) {
|
|
1637
|
+
return;
|
|
1638
|
+
}
|
|
1639
|
+
if (instance.anchor && instance.anchor.contains(target)) {
|
|
1640
|
+
return;
|
|
1641
|
+
}
|
|
1642
|
+
if (!instance.closeOnOutsideClick || (instance.canClose && !instance.canClose())) {
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
if (event.target !== instance.backdrop) {
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
instance.cleanup();
|
|
1084
1649
|
};
|
|
1085
|
-
|
|
1086
|
-
const
|
|
1087
|
-
if (!
|
|
1650
|
+
onDocumentContextMenu = (event) => {
|
|
1651
|
+
const instance = this.getLastInstance();
|
|
1652
|
+
if (!instance) {
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
if (instance.point && instance.anchor && instance.anchor.contains(event.target)) {
|
|
1656
|
+
event.preventDefault();
|
|
1657
|
+
instance.point = {
|
|
1658
|
+
x: event.clientX,
|
|
1659
|
+
y: event.clientY,
|
|
1660
|
+
};
|
|
1661
|
+
this.scheduleReposition();
|
|
1088
1662
|
return;
|
|
1089
|
-
|
|
1090
|
-
if (event.target
|
|
1663
|
+
}
|
|
1664
|
+
if (instance.element.contains(event.target)) {
|
|
1091
1665
|
return;
|
|
1092
|
-
|
|
1093
|
-
if (
|
|
1666
|
+
}
|
|
1667
|
+
if (!instance.closeOnOutsideClick || (instance.canClose && !instance.canClose())) {
|
|
1094
1668
|
return;
|
|
1095
|
-
const rect = lastDialog.element.getBoundingClientRect();
|
|
1096
|
-
const clickWasInsideDialog = rect.top <= event.clientY &&
|
|
1097
|
-
event.clientY <= rect.bottom &&
|
|
1098
|
-
rect.left <= event.clientX &&
|
|
1099
|
-
event.clientX <= rect.right;
|
|
1100
|
-
const anchRect = lastDialog.anchor.getBoundingClientRect();
|
|
1101
|
-
const clickWasInsideAnchor = anchRect.top <= event.clientY &&
|
|
1102
|
-
event.clientY <= anchRect.bottom &&
|
|
1103
|
-
anchRect.left <= event.clientX &&
|
|
1104
|
-
event.clientX <= anchRect.right;
|
|
1105
|
-
if (!clickWasInsideDialog) {
|
|
1106
|
-
if (event.type == 'contextmenu' && lastDialog.point && clickWasInsideAnchor) {
|
|
1107
|
-
event.preventDefault();
|
|
1108
|
-
lastDialog.point = {
|
|
1109
|
-
x: event.clientX,
|
|
1110
|
-
y: event.clientY,
|
|
1111
|
-
};
|
|
1112
|
-
this.positionDialog(lastDialog);
|
|
1113
|
-
}
|
|
1114
|
-
else {
|
|
1115
|
-
lastDialog.cleanup();
|
|
1116
|
-
}
|
|
1117
1669
|
}
|
|
1670
|
+
if (event.target !== instance.backdrop) {
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1673
|
+
instance.cleanup();
|
|
1674
|
+
};
|
|
1675
|
+
onDocumentScroll = () => {
|
|
1676
|
+
this.scheduleReposition();
|
|
1677
|
+
};
|
|
1678
|
+
onWindowResize = () => {
|
|
1679
|
+
this.scheduleReposition();
|
|
1680
|
+
};
|
|
1681
|
+
scheduleReposition() {
|
|
1682
|
+
if (this.layoutRaf !== null) {
|
|
1683
|
+
return;
|
|
1684
|
+
}
|
|
1685
|
+
this.layoutRaf = this.requestAnimationFrame(() => {
|
|
1686
|
+
this.layoutRaf = null;
|
|
1687
|
+
const instances = [...this.overlayStack];
|
|
1688
|
+
for (const instance of instances) {
|
|
1689
|
+
this.positionOverlay(instance);
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1118
1692
|
}
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
this.positionDialog(instance);
|
|
1693
|
+
// ---------------------------------------------------------------------------
|
|
1694
|
+
// focus
|
|
1695
|
+
// ---------------------------------------------------------------------------
|
|
1696
|
+
scheduleInitialLayout(instance) {
|
|
1697
|
+
instance.rafId = this.requestAnimationFrame(() => {
|
|
1698
|
+
instance.rafId = null;
|
|
1699
|
+
this.positionOverlay(instance);
|
|
1700
|
+
if (!instance.autoFocus) {
|
|
1701
|
+
return;
|
|
1129
1702
|
}
|
|
1703
|
+
instance.focusTimeoutId = setTimeout(() => {
|
|
1704
|
+
instance.focusTimeoutId = null;
|
|
1705
|
+
this.focusInitialElement(instance);
|
|
1706
|
+
}, 0);
|
|
1130
1707
|
});
|
|
1131
1708
|
}
|
|
1132
|
-
|
|
1133
|
-
const
|
|
1134
|
-
|
|
1135
|
-
|
|
1709
|
+
focusInitialElement(instance) {
|
|
1710
|
+
const focusable = instance.element.querySelector(FOCUSABLE_SELECTOR);
|
|
1711
|
+
focusable?.focus() ?? instance.element.focus();
|
|
1712
|
+
}
|
|
1713
|
+
trapFocus(event, instance) {
|
|
1714
|
+
const elements = Array.from(instance.element.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
1715
|
+
if (!elements.length) {
|
|
1716
|
+
event.preventDefault();
|
|
1717
|
+
instance.element.focus();
|
|
1136
1718
|
return;
|
|
1137
|
-
let anchorRect;
|
|
1138
|
-
if (point) {
|
|
1139
|
-
anchorRect = new DOMRect(point.x, point.y, 0, 0);
|
|
1140
1719
|
}
|
|
1141
|
-
|
|
1142
|
-
|
|
1720
|
+
const first = elements[0];
|
|
1721
|
+
const last = elements[elements.length - 1];
|
|
1722
|
+
const active = this.getActiveElement();
|
|
1723
|
+
if (!event.shiftKey && active === last) {
|
|
1724
|
+
event.preventDefault();
|
|
1725
|
+
first.focus();
|
|
1726
|
+
return;
|
|
1143
1727
|
}
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
const isRTL = this.directionService.isRtl();
|
|
1148
|
-
let top = 0;
|
|
1149
|
-
let left = 'auto';
|
|
1150
|
-
let right = 'auto';
|
|
1151
|
-
const spaceBelow = vh - anchorRect.bottom;
|
|
1152
|
-
const spaceAbove = anchorRect.top;
|
|
1153
|
-
let verticalPos = 'above';
|
|
1154
|
-
if (placement === 'bottom' ||
|
|
1155
|
-
(placement === 'auto' && spaceBelow >= dialogRect.height + margin)) {
|
|
1156
|
-
top = anchorRect.bottom + margin;
|
|
1157
|
-
verticalPos = 'above';
|
|
1158
|
-
if (top + dialogRect.height > vh - margin) {
|
|
1159
|
-
top = vh - dialogRect.height - margin;
|
|
1160
|
-
verticalPos = 'bottom';
|
|
1161
|
-
}
|
|
1728
|
+
if (event.shiftKey && active === first) {
|
|
1729
|
+
event.preventDefault();
|
|
1730
|
+
last.focus();
|
|
1162
1731
|
}
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1732
|
+
}
|
|
1733
|
+
restoreFocus(element) {
|
|
1734
|
+
if (element && element.isConnected) {
|
|
1735
|
+
setTimeout(() => {
|
|
1736
|
+
element.focus();
|
|
1737
|
+
}, 0);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
getActiveElement() {
|
|
1741
|
+
const active = this.document.activeElement;
|
|
1742
|
+
return active instanceof HTMLElement ? active : null;
|
|
1743
|
+
}
|
|
1744
|
+
// ---------------------------------------------------------------------------
|
|
1745
|
+
// positioning
|
|
1746
|
+
// ---------------------------------------------------------------------------
|
|
1747
|
+
positionOverlay(instance) {
|
|
1748
|
+
if (!instance.host.isConnected || !instance.element.isConnected) {
|
|
1749
|
+
return;
|
|
1170
1750
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1751
|
+
const viewportWidth = window.innerWidth;
|
|
1752
|
+
const viewportHeight = window.innerHeight;
|
|
1753
|
+
const anchorRect = this.getAnchorRect(instance);
|
|
1754
|
+
const overlay = instance.element;
|
|
1755
|
+
const overlayRect = overlay.getBoundingClientRect();
|
|
1756
|
+
const { placement, alignment, margin } = instance.placementConfig;
|
|
1757
|
+
const isRTL = this.directionService.isRtl();
|
|
1758
|
+
let top;
|
|
1759
|
+
if (placement === 'center') {
|
|
1760
|
+
top = anchorRect.top + anchorRect.height / 2 - overlayRect.height / 2;
|
|
1173
1761
|
}
|
|
1174
|
-
else
|
|
1175
|
-
|
|
1176
|
-
|
|
1762
|
+
else {
|
|
1763
|
+
const spaceBelow = viewportHeight - anchorRect.bottom;
|
|
1764
|
+
const placeBelow = placement === 'bottom' ||
|
|
1765
|
+
(placement === 'auto' && spaceBelow >= overlayRect.height + margin);
|
|
1766
|
+
if (placeBelow) {
|
|
1767
|
+
top = anchorRect.bottom + margin;
|
|
1177
1768
|
}
|
|
1178
1769
|
else {
|
|
1179
|
-
|
|
1770
|
+
top = anchorRect.top - overlayRect.height - margin;
|
|
1180
1771
|
}
|
|
1772
|
+
overlay.classList.toggle('tips-below', placeBelow);
|
|
1773
|
+
overlay.classList.toggle('tips-above', !placeBelow);
|
|
1181
1774
|
}
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1775
|
+
if (top + overlayRect.height > viewportHeight - margin) {
|
|
1776
|
+
top = viewportHeight - overlayRect.height - margin;
|
|
1777
|
+
}
|
|
1778
|
+
if (top < margin) {
|
|
1779
|
+
top = margin;
|
|
1780
|
+
}
|
|
1781
|
+
let left;
|
|
1782
|
+
switch (alignment) {
|
|
1783
|
+
case 'center':
|
|
1784
|
+
left = anchorRect.left + anchorRect.width / 2 - overlayRect.width / 2;
|
|
1785
|
+
break;
|
|
1786
|
+
case 'end':
|
|
1787
|
+
left = isRTL ? anchorRect.left : anchorRect.right - overlayRect.width;
|
|
1788
|
+
break;
|
|
1789
|
+
case 'start':
|
|
1790
|
+
default:
|
|
1791
|
+
left = isRTL ? anchorRect.right - overlayRect.width : anchorRect.left;
|
|
1792
|
+
break;
|
|
1193
1793
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1794
|
+
left = Math.min(Math.max(left, margin), Math.max(margin, viewportWidth - overlayRect.width - margin));
|
|
1795
|
+
overlay.style.top = `${Math.round(top)}px`;
|
|
1796
|
+
overlay.style.left = `${Math.round(left)}px`;
|
|
1797
|
+
overlay.style.right = 'auto';
|
|
1798
|
+
overlay.style.bottom = 'auto';
|
|
1799
|
+
overlay.style.visibility = 'visible';
|
|
1800
|
+
// NOTE: showPopover() is intentionally NOT called here. It already
|
|
1801
|
+
// happened once in renderHost(); calling it again on every reposition
|
|
1802
|
+
// (scroll/resize) throws InvalidStateError since the popover is
|
|
1803
|
+
// already open.
|
|
1804
|
+
}
|
|
1805
|
+
getAnchorRect(instance) {
|
|
1806
|
+
if (instance.point) {
|
|
1807
|
+
return new DOMRect(instance.point.x, instance.point.y, 0, 0);
|
|
1808
|
+
}
|
|
1809
|
+
if (instance.anchor && instance.anchor.isConnected) {
|
|
1810
|
+
return instance.anchor.getBoundingClientRect();
|
|
1811
|
+
}
|
|
1812
|
+
return new DOMRect(window.innerWidth / 2, window.innerHeight / 2, 0, 0);
|
|
1813
|
+
}
|
|
1814
|
+
resolvePlacementConfig(placement, alignment, margin) {
|
|
1815
|
+
return {
|
|
1816
|
+
placement: placement ?? 'auto',
|
|
1817
|
+
alignment: alignment ?? 'start',
|
|
1818
|
+
margin: margin ?? 8,
|
|
1819
|
+
};
|
|
1820
|
+
}
|
|
1821
|
+
// ---------------------------------------------------------------------------
|
|
1822
|
+
// utilities
|
|
1823
|
+
// ---------------------------------------------------------------------------
|
|
1824
|
+
getLastInstance() {
|
|
1825
|
+
return this.overlayStack[this.overlayStack.length - 1];
|
|
1826
|
+
}
|
|
1827
|
+
requestAnimationFrame(callback) {
|
|
1828
|
+
if (typeof window.requestAnimationFrame === 'function') {
|
|
1829
|
+
return window.requestAnimationFrame(callback);
|
|
1196
1830
|
}
|
|
1197
|
-
|
|
1198
|
-
|
|
1831
|
+
return window.setTimeout(() => callback(Date.now()), 16);
|
|
1832
|
+
}
|
|
1833
|
+
cancelAnimationFrame(id) {
|
|
1834
|
+
if (typeof window.cancelAnimationFrame === 'function') {
|
|
1835
|
+
window.cancelAnimationFrame(id);
|
|
1199
1836
|
}
|
|
1200
|
-
|
|
1201
|
-
|
|
1837
|
+
else {
|
|
1838
|
+
clearTimeout(id);
|
|
1202
1839
|
}
|
|
1203
|
-
dialog.className = `${DIALOG_OVERLAY_CLASSNAME} tips-${verticalPos}`;
|
|
1204
|
-
dialog.style.top = `${top + window.scrollY}px`;
|
|
1205
|
-
dialog.style.left = left !== 'auto' ? `${left + window.scrollX}px` : 'auto';
|
|
1206
|
-
dialog.style.right = right !== 'auto' ? `${right + window.scrollX}px` : 'auto';
|
|
1207
|
-
dialog.style.transformOrigin = verticalPos == 'above' ? 'left top' : 'left bottom';
|
|
1208
|
-
// dialog.style.transform = 'none';
|
|
1209
|
-
dialog.style.visibility = 'visible';
|
|
1210
|
-
dialog.style.animation = 'menu-enter 120ms cubic-bezier(0, 0, 0.2, 1)';
|
|
1211
1840
|
}
|
|
1212
1841
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: OverlayService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1213
1842
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: OverlayService, providedIn: 'root' });
|
|
1214
1843
|
}
|
|
1215
1844
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: OverlayService, decorators: [{
|
|
1216
1845
|
type: Injectable,
|
|
1217
|
-
args: [{
|
|
1846
|
+
args: [{
|
|
1847
|
+
providedIn: 'root',
|
|
1848
|
+
}]
|
|
1218
1849
|
}] });
|
|
1219
1850
|
|
|
1220
1851
|
/**
|
|
1221
1852
|
* Generated bundle index. Do not edit.
|
|
1222
1853
|
*/
|
|
1223
1854
|
|
|
1224
|
-
export { BrowserService, DIALOG_OVERLAY_CLASSNAME, DirectionService, FOCUSABLE_SELECTOR, OverlayRef, OverlayService, RangeSliderComponent, SaturationComponent, SliderComponent, ValueModel, WINDOW, generateSequentialGuid, getOffsetPosition, makeConfetti,
|
|
1225
|
-
//# sourceMappingURL=ngx-kit-
|
|
1855
|
+
export { BrowserService, CSS_COLOR_NAMES, DIALOG_OVERLAY_CLASSNAME, DirectionService, FOCUSABLE_SELECTOR, OVERLAY_HOST_CLASSNAME, OverlayRef, OverlayService, RangeSliderComponent, SaturationComponent, SliderComponent, ValueModel, WINDOW, extractCssColors, filterTreeList, generateSequentialGuid, getOffsetPosition, makeConfetti, mergeDeep, randomStrnig, startDragSession };
|
|
1856
|
+
//# sourceMappingURL=ngx-kit-core.mjs.map
|