@helsevestikt/hviktor-angular 0.0.11 → 0.0.13
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.
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
2
|
import { Input, Component, booleanAttribute, Directive, CUSTOM_ELEMENTS_SCHEMA, EventEmitter, inject, ElementRef, HostListener, Output, ViewChild, DestroyRef, HostBinding, ChangeDetectorRef, ViewEncapsulation } from '@angular/core';
|
|
3
3
|
import '@u-elements/u-details';
|
|
4
|
-
import { FormGroupDirective, NgControl, ControlContainer, ReactiveFormsModule } from '@angular/forms';
|
|
4
|
+
import { FormGroupDirective, NgControl, ControlContainer, Validators, ReactiveFormsModule } from '@angular/forms';
|
|
5
5
|
import { HttpClient } from '@angular/common/http';
|
|
6
|
+
import { computePosition, offset, flip, shift, autoUpdate } from '@floating-ui/dom';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Alert provides users with information that is especially important for them to see and understand.
|
|
@@ -1010,117 +1011,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
1010
1011
|
args: ['container', { static: true }]
|
|
1011
1012
|
}] } });
|
|
1012
1013
|
|
|
1013
|
-
/**
|
|
1014
|
-
* Decorative affix container displayed alongside a text input.
|
|
1015
|
-
*
|
|
1016
|
-
* @remarks
|
|
1017
|
-
* Used together with the `hvi-field-affixes` component to wrap leading and trailing adornments.
|
|
1018
|
-
*
|
|
1019
|
-
* @example
|
|
1020
|
-
* ```html
|
|
1021
|
-
* <hvi-field-affixes>
|
|
1022
|
-
* <hvi-field-affix>NOK</hvi-field-affix>
|
|
1023
|
-
* <input hviInput type="text" placeholder="Amount" />
|
|
1024
|
-
* <hvi-field-affix>per month</hvi-field-affix>
|
|
1025
|
-
* </hvi-field-affixes>
|
|
1026
|
-
* ```
|
|
1027
|
-
*
|
|
1028
|
-
* Documentation: https://designsystemet.no/en/components/docs/field/code#prefixsuffix
|
|
1029
|
-
*/
|
|
1030
|
-
class HviFieldAffix {
|
|
1031
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldAffix, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1032
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldAffix, isStandalone: true, selector: "hvi-field-affix", host: { properties: { "aria-hidden": "true" }, classAttribute: "ds-field-affix" }, ngImport: i0, template: `<ng-content />`, isInline: true });
|
|
1033
|
-
}
|
|
1034
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldAffix, decorators: [{
|
|
1035
|
-
type: Component,
|
|
1036
|
-
args: [{
|
|
1037
|
-
selector: 'hvi-field-affix',
|
|
1038
|
-
template: `<ng-content />`,
|
|
1039
|
-
host: {
|
|
1040
|
-
class: 'ds-field-affix',
|
|
1041
|
-
'[aria-hidden]': 'true',
|
|
1042
|
-
},
|
|
1043
|
-
}]
|
|
1044
|
-
}] });
|
|
1045
|
-
|
|
1046
|
-
/**
|
|
1047
|
-
* Container for decorative affixes displayed alongside a text input.
|
|
1048
|
-
*
|
|
1049
|
-
* @remarks
|
|
1050
|
-
* Wraps leading and trailing adornments provided by `hvi-field-affix` components.
|
|
1051
|
-
*
|
|
1052
|
-
* @example
|
|
1053
|
-
* ```html
|
|
1054
|
-
* <hvi-field-affixes>
|
|
1055
|
-
* <hvi-field-affix>NOK</hvi-field-affix>
|
|
1056
|
-
* <input hviInput type="text" placeholder="Amount" />
|
|
1057
|
-
* <hvi-field-affix>per month</hvi-field-affix>
|
|
1058
|
-
* </hvi-field-affixes>
|
|
1059
|
-
* ```
|
|
1060
|
-
*
|
|
1061
|
-
* Documentation: https://designsystemet.no/en/components/docs/field/code#prefixsuffix
|
|
1062
|
-
*/
|
|
1063
|
-
class HviFieldAffixes {
|
|
1064
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldAffixes, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1065
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldAffixes, isStandalone: true, selector: "hvi-field-affixes", host: { classAttribute: "ds-field-affixes" }, ngImport: i0, template: `<ng-content />`, isInline: true });
|
|
1066
|
-
}
|
|
1067
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldAffixes, decorators: [{
|
|
1068
|
-
type: Component,
|
|
1069
|
-
args: [{
|
|
1070
|
-
selector: 'hvi-field-affixes',
|
|
1071
|
-
template: `<ng-content />`,
|
|
1072
|
-
host: {
|
|
1073
|
-
class: 'ds-field-affixes',
|
|
1074
|
-
},
|
|
1075
|
-
}]
|
|
1076
|
-
}] });
|
|
1077
|
-
|
|
1078
|
-
class HviFieldDescription {
|
|
1079
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldDescription, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1080
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldDescription, isStandalone: true, selector: "[hviFieldDescription]", host: { attributes: { "data-field": "description" } }, ngImport: i0 });
|
|
1081
|
-
}
|
|
1082
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldDescription, decorators: [{
|
|
1083
|
-
type: Directive,
|
|
1084
|
-
args: [{
|
|
1085
|
-
selector: '[hviFieldDescription]',
|
|
1086
|
-
standalone: true,
|
|
1087
|
-
host: {
|
|
1088
|
-
'data-field': 'description',
|
|
1089
|
-
},
|
|
1090
|
-
}]
|
|
1091
|
-
}] });
|
|
1092
|
-
|
|
1093
|
-
class HviFieldOptional {
|
|
1094
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldOptional, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1095
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldOptional, isStandalone: true, selector: "[hviFieldOptional]", host: { attributes: { "data-field": "optional" } }, ngImport: i0 });
|
|
1096
|
-
}
|
|
1097
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldOptional, decorators: [{
|
|
1098
|
-
type: Directive,
|
|
1099
|
-
args: [{
|
|
1100
|
-
selector: '[hviFieldOptional]',
|
|
1101
|
-
standalone: true,
|
|
1102
|
-
host: {
|
|
1103
|
-
'data-field': 'optional',
|
|
1104
|
-
},
|
|
1105
|
-
}]
|
|
1106
|
-
}] });
|
|
1107
|
-
|
|
1108
|
-
class HviFieldValidation {
|
|
1109
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldValidation, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1110
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldValidation, isStandalone: true, selector: "[hviFieldValidation]", host: { attributes: { "data-field": "validation" }, classAttribute: "ds-validation-message" }, ngImport: i0 });
|
|
1111
|
-
}
|
|
1112
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldValidation, decorators: [{
|
|
1113
|
-
type: Directive,
|
|
1114
|
-
args: [{
|
|
1115
|
-
selector: '[hviFieldValidation]',
|
|
1116
|
-
standalone: true,
|
|
1117
|
-
host: {
|
|
1118
|
-
class: 'ds-validation-message',
|
|
1119
|
-
'data-field': 'validation',
|
|
1120
|
-
},
|
|
1121
|
-
}]
|
|
1122
|
-
}] });
|
|
1123
|
-
|
|
1124
1014
|
// Copied from https://github.com/digdir/designsystemet/blob/main/packages/react/src/components/field/field-observer.ts
|
|
1125
1015
|
function fieldObserver(fieldElement) {
|
|
1126
1016
|
if (!fieldElement)
|
|
@@ -1235,6 +1125,117 @@ function createOptimizedMutationObserver(callback) {
|
|
|
1235
1125
|
return observer;
|
|
1236
1126
|
}
|
|
1237
1127
|
|
|
1128
|
+
/**
|
|
1129
|
+
* Decorative affix container displayed alongside a text input.
|
|
1130
|
+
*
|
|
1131
|
+
* @remarks
|
|
1132
|
+
* Used together with the `hvi-field-affixes` component to wrap leading and trailing adornments.
|
|
1133
|
+
*
|
|
1134
|
+
* @example
|
|
1135
|
+
* ```html
|
|
1136
|
+
* <hvi-field-affixes>
|
|
1137
|
+
* <hvi-field-affix>NOK</hvi-field-affix>
|
|
1138
|
+
* <input hviInput type="text" placeholder="Amount" />
|
|
1139
|
+
* <hvi-field-affix>per month</hvi-field-affix>
|
|
1140
|
+
* </hvi-field-affixes>
|
|
1141
|
+
* ```
|
|
1142
|
+
*
|
|
1143
|
+
* Documentation: https://designsystemet.no/en/components/docs/field/code#prefixsuffix
|
|
1144
|
+
*/
|
|
1145
|
+
class HviFieldAffix {
|
|
1146
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldAffix, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1147
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldAffix, isStandalone: true, selector: "hvi-field-affix", host: { properties: { "aria-hidden": "true" }, classAttribute: "ds-field-affix" }, ngImport: i0, template: `<ng-content />`, isInline: true });
|
|
1148
|
+
}
|
|
1149
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldAffix, decorators: [{
|
|
1150
|
+
type: Component,
|
|
1151
|
+
args: [{
|
|
1152
|
+
selector: 'hvi-field-affix',
|
|
1153
|
+
template: `<ng-content />`,
|
|
1154
|
+
host: {
|
|
1155
|
+
class: 'ds-field-affix',
|
|
1156
|
+
'[aria-hidden]': 'true',
|
|
1157
|
+
},
|
|
1158
|
+
}]
|
|
1159
|
+
}] });
|
|
1160
|
+
|
|
1161
|
+
/**
|
|
1162
|
+
* Container for decorative affixes displayed alongside a text input.
|
|
1163
|
+
*
|
|
1164
|
+
* @remarks
|
|
1165
|
+
* Wraps leading and trailing adornments provided by `hvi-field-affix` components.
|
|
1166
|
+
*
|
|
1167
|
+
* @example
|
|
1168
|
+
* ```html
|
|
1169
|
+
* <hvi-field-affixes>
|
|
1170
|
+
* <hvi-field-affix>NOK</hvi-field-affix>
|
|
1171
|
+
* <input hviInput type="text" placeholder="Amount" />
|
|
1172
|
+
* <hvi-field-affix>per month</hvi-field-affix>
|
|
1173
|
+
* </hvi-field-affixes>
|
|
1174
|
+
* ```
|
|
1175
|
+
*
|
|
1176
|
+
* Documentation: https://designsystemet.no/en/components/docs/field/code#prefixsuffix
|
|
1177
|
+
*/
|
|
1178
|
+
class HviFieldAffixes {
|
|
1179
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldAffixes, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1180
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldAffixes, isStandalone: true, selector: "hvi-field-affixes", host: { classAttribute: "ds-field-affixes" }, ngImport: i0, template: `<ng-content />`, isInline: true });
|
|
1181
|
+
}
|
|
1182
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldAffixes, decorators: [{
|
|
1183
|
+
type: Component,
|
|
1184
|
+
args: [{
|
|
1185
|
+
selector: 'hvi-field-affixes',
|
|
1186
|
+
template: `<ng-content />`,
|
|
1187
|
+
host: {
|
|
1188
|
+
class: 'ds-field-affixes',
|
|
1189
|
+
},
|
|
1190
|
+
}]
|
|
1191
|
+
}] });
|
|
1192
|
+
|
|
1193
|
+
class HviFieldDescription {
|
|
1194
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldDescription, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1195
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldDescription, isStandalone: true, selector: "[hviFieldDescription]", host: { attributes: { "data-field": "description" } }, ngImport: i0 });
|
|
1196
|
+
}
|
|
1197
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldDescription, decorators: [{
|
|
1198
|
+
type: Directive,
|
|
1199
|
+
args: [{
|
|
1200
|
+
selector: '[hviFieldDescription]',
|
|
1201
|
+
standalone: true,
|
|
1202
|
+
host: {
|
|
1203
|
+
'data-field': 'description',
|
|
1204
|
+
},
|
|
1205
|
+
}]
|
|
1206
|
+
}] });
|
|
1207
|
+
|
|
1208
|
+
class HviFieldOptional {
|
|
1209
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldOptional, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1210
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldOptional, isStandalone: true, selector: "[hviFieldOptional]", host: { attributes: { "data-field": "optional" } }, ngImport: i0 });
|
|
1211
|
+
}
|
|
1212
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldOptional, decorators: [{
|
|
1213
|
+
type: Directive,
|
|
1214
|
+
args: [{
|
|
1215
|
+
selector: '[hviFieldOptional]',
|
|
1216
|
+
standalone: true,
|
|
1217
|
+
host: {
|
|
1218
|
+
'data-field': 'optional',
|
|
1219
|
+
},
|
|
1220
|
+
}]
|
|
1221
|
+
}] });
|
|
1222
|
+
|
|
1223
|
+
class HviFieldValidation {
|
|
1224
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldValidation, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1225
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.1.2", type: HviFieldValidation, isStandalone: true, selector: "[hviFieldValidation]", host: { attributes: { "data-field": "validation" }, classAttribute: "ds-validation-message" }, ngImport: i0 });
|
|
1226
|
+
}
|
|
1227
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviFieldValidation, decorators: [{
|
|
1228
|
+
type: Directive,
|
|
1229
|
+
args: [{
|
|
1230
|
+
selector: '[hviFieldValidation]',
|
|
1231
|
+
standalone: true,
|
|
1232
|
+
host: {
|
|
1233
|
+
class: 'ds-validation-message',
|
|
1234
|
+
'data-field': 'validation',
|
|
1235
|
+
},
|
|
1236
|
+
}]
|
|
1237
|
+
}] });
|
|
1238
|
+
|
|
1238
1239
|
/**
|
|
1239
1240
|
* Field is a helper component to automatically associate a field with hviLabel, hviFieldDescription and hviFieldValidation.
|
|
1240
1241
|
*
|
|
@@ -1319,7 +1320,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
1319
1320
|
}] });
|
|
1320
1321
|
|
|
1321
1322
|
class HviInput {
|
|
1323
|
+
/** Supported input types */
|
|
1322
1324
|
type;
|
|
1325
|
+
/** Set size attribute on input element */
|
|
1323
1326
|
size;
|
|
1324
1327
|
/** Set role, e.g. `switch` when `checkbox` or `radio` */
|
|
1325
1328
|
role;
|
|
@@ -1516,6 +1519,158 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
1516
1519
|
type: Input
|
|
1517
1520
|
}] } });
|
|
1518
1521
|
|
|
1522
|
+
/**
|
|
1523
|
+
* Extracts validators and messages from an array of validator bundles.
|
|
1524
|
+
*
|
|
1525
|
+
* @example
|
|
1526
|
+
* ```ts
|
|
1527
|
+
* const config = hviValidators([
|
|
1528
|
+
* hviRequired('Fornavn er påkrevd'),
|
|
1529
|
+
* hviMinLength(2, 'Fornavn må være minst 2 tegn'),
|
|
1530
|
+
* ]);
|
|
1531
|
+
*
|
|
1532
|
+
* form = new FormGroup({
|
|
1533
|
+
* firstName: new FormControl('', config.validators),
|
|
1534
|
+
* });
|
|
1535
|
+
*
|
|
1536
|
+
* // In template: [messages]="config.messages"
|
|
1537
|
+
* ```
|
|
1538
|
+
*/
|
|
1539
|
+
function hviValidators(bundles) {
|
|
1540
|
+
return {
|
|
1541
|
+
validators: bundles.map((b) => b.validator),
|
|
1542
|
+
messages: bundles.reduce((acc, b) => ({ ...acc, [b.key]: b.message }), {}),
|
|
1543
|
+
};
|
|
1544
|
+
}
|
|
1545
|
+
/**
|
|
1546
|
+
* Extracts only the validator functions from bundles.
|
|
1547
|
+
* Useful when you need just the validators for a FormControl.
|
|
1548
|
+
*/
|
|
1549
|
+
function hviExtractValidators(bundles) {
|
|
1550
|
+
return bundles.map((b) => b.validator);
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Extracts only the messages from bundles.
|
|
1554
|
+
* Useful when you need just the messages object.
|
|
1555
|
+
*/
|
|
1556
|
+
function hviExtractMessages(bundles) {
|
|
1557
|
+
return bundles.reduce((acc, b) => ({ ...acc, [b.key]: b.message }), {});
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
/**
|
|
1561
|
+
* Creates a required validator bundle.
|
|
1562
|
+
*
|
|
1563
|
+
* @example
|
|
1564
|
+
* ```ts
|
|
1565
|
+
* hviRequired('Dette feltet er påkrevd')
|
|
1566
|
+
* ```
|
|
1567
|
+
*/
|
|
1568
|
+
function hviRequired(message) {
|
|
1569
|
+
return { validator: Validators.required, key: 'required', message };
|
|
1570
|
+
}
|
|
1571
|
+
/**
|
|
1572
|
+
* Creates a requiredTrue validator bundle (for checkboxes that must be checked).
|
|
1573
|
+
*
|
|
1574
|
+
* @example
|
|
1575
|
+
* ```ts
|
|
1576
|
+
* hviRequiredTrue('Du må godta vilkårene')
|
|
1577
|
+
* ```
|
|
1578
|
+
*/
|
|
1579
|
+
function hviRequiredTrue(message) {
|
|
1580
|
+
return { validator: Validators.requiredTrue, key: 'required', message };
|
|
1581
|
+
}
|
|
1582
|
+
/**
|
|
1583
|
+
* Creates a minLength validator bundle.
|
|
1584
|
+
*
|
|
1585
|
+
* @example
|
|
1586
|
+
* ```ts
|
|
1587
|
+
* hviMinLength(2, 'Må være minst 2 tegn')
|
|
1588
|
+
* ```
|
|
1589
|
+
*/
|
|
1590
|
+
function hviMinLength(length, message) {
|
|
1591
|
+
return { validator: Validators.minLength(length), key: 'minlength', message };
|
|
1592
|
+
}
|
|
1593
|
+
/**
|
|
1594
|
+
* Creates a maxLength validator bundle.
|
|
1595
|
+
*
|
|
1596
|
+
* @example
|
|
1597
|
+
* ```ts
|
|
1598
|
+
* hviMaxLength(100, 'Kan ikke være mer enn 100 tegn')
|
|
1599
|
+
* ```
|
|
1600
|
+
*/
|
|
1601
|
+
function hviMaxLength(length, message) {
|
|
1602
|
+
return { validator: Validators.maxLength(length), key: 'maxlength', message };
|
|
1603
|
+
}
|
|
1604
|
+
/**
|
|
1605
|
+
* Creates an email validator bundle.
|
|
1606
|
+
*
|
|
1607
|
+
* @example
|
|
1608
|
+
* ```ts
|
|
1609
|
+
* hviEmail('Ugyldig e-postadresse')
|
|
1610
|
+
* ```
|
|
1611
|
+
*/
|
|
1612
|
+
function hviEmail(message) {
|
|
1613
|
+
return { validator: Validators.email, key: 'email', message };
|
|
1614
|
+
}
|
|
1615
|
+
/**
|
|
1616
|
+
* Creates a pattern validator bundle.
|
|
1617
|
+
*
|
|
1618
|
+
* @example
|
|
1619
|
+
* ```ts
|
|
1620
|
+
* hviPattern(/^\d+$/, 'Kan kun inneholde tall')
|
|
1621
|
+
* ```
|
|
1622
|
+
*/
|
|
1623
|
+
function hviPattern(pattern, message) {
|
|
1624
|
+
return { validator: Validators.pattern(pattern), key: 'pattern', message };
|
|
1625
|
+
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Creates a min value validator bundle.
|
|
1628
|
+
*
|
|
1629
|
+
* @example
|
|
1630
|
+
* ```ts
|
|
1631
|
+
* hviMin(0, 'Må være minst 0')
|
|
1632
|
+
* ```
|
|
1633
|
+
*/
|
|
1634
|
+
function hviMin(min, message) {
|
|
1635
|
+
return { validator: Validators.min(min), key: 'min', message };
|
|
1636
|
+
}
|
|
1637
|
+
/**
|
|
1638
|
+
* Creates a max value validator bundle.
|
|
1639
|
+
*
|
|
1640
|
+
* @example
|
|
1641
|
+
* ```ts
|
|
1642
|
+
* hviMax(100, 'Kan ikke være mer enn 100')
|
|
1643
|
+
* ```
|
|
1644
|
+
*/
|
|
1645
|
+
function hviMax(max, message) {
|
|
1646
|
+
return { validator: Validators.max(max), key: 'max', message };
|
|
1647
|
+
}
|
|
1648
|
+
/**
|
|
1649
|
+
* Creates a custom validator bundle with a specified error key.
|
|
1650
|
+
* Use this for custom validators or validators not covered by the built-in functions.
|
|
1651
|
+
*
|
|
1652
|
+
* @example
|
|
1653
|
+
* ```ts
|
|
1654
|
+
* // Custom validator that checks if value matches a specific format
|
|
1655
|
+
* const norwegianPhoneValidator: ValidatorFn = (control) => {
|
|
1656
|
+
* const valid = /^(\+47)?\d{8}$/.test(control.value);
|
|
1657
|
+
* return valid ? null : { norwegianPhone: true };
|
|
1658
|
+
* };
|
|
1659
|
+
*
|
|
1660
|
+
* hviCustom('norwegianPhone', norwegianPhoneValidator, 'Ugyldig norsk telefonnummer')
|
|
1661
|
+
* ```
|
|
1662
|
+
*/
|
|
1663
|
+
function hviCustom(key, validator, message) {
|
|
1664
|
+
return { validator, key, message };
|
|
1665
|
+
}
|
|
1666
|
+
/**
|
|
1667
|
+
* Creates a nullValidator bundle (always valid, useful for conditional validation).
|
|
1668
|
+
* Note: This validator always passes, so the message will never be shown.
|
|
1669
|
+
*/
|
|
1670
|
+
function hviNullValidator() {
|
|
1671
|
+
return { validator: Validators.nullValidator, key: 'null', message: '' };
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1519
1674
|
// 1) Bare field-byggesteiner
|
|
1520
1675
|
const HviFieldKit = [
|
|
1521
1676
|
HviField,
|
|
@@ -1753,6 +1908,205 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
1753
1908
|
type: Input
|
|
1754
1909
|
}] } });
|
|
1755
1910
|
|
|
1911
|
+
const arrowPseudoElement = {
|
|
1912
|
+
name: 'ArrowPseudoElement',
|
|
1913
|
+
fn(data) {
|
|
1914
|
+
const { elements, rects, placement } = data;
|
|
1915
|
+
let arrowX = `${Math.round(rects.reference.width / 2 + rects.reference.x - data.x)}px`;
|
|
1916
|
+
let arrowY = `${Math.round(rects.reference.height / 2 + rects.reference.y - data.y)}px`;
|
|
1917
|
+
if (rects.reference.width > rects.floating.width) {
|
|
1918
|
+
arrowX = `${Math.round(rects.floating.width / 2)}px`;
|
|
1919
|
+
}
|
|
1920
|
+
if (rects.reference.height > rects.floating.height) {
|
|
1921
|
+
arrowY = `${Math.round(rects.floating.height / 2)}px`;
|
|
1922
|
+
}
|
|
1923
|
+
switch (placement.split('-')[0]) {
|
|
1924
|
+
case 'top':
|
|
1925
|
+
arrowY = '100%';
|
|
1926
|
+
break;
|
|
1927
|
+
case 'right':
|
|
1928
|
+
arrowX = '0';
|
|
1929
|
+
break;
|
|
1930
|
+
case 'bottom':
|
|
1931
|
+
arrowY = '0';
|
|
1932
|
+
break;
|
|
1933
|
+
case 'left':
|
|
1934
|
+
arrowX = '100%';
|
|
1935
|
+
break;
|
|
1936
|
+
}
|
|
1937
|
+
elements.floating.setAttribute('data-placement', placement.split('-')[0]);
|
|
1938
|
+
elements.floating.style.setProperty('--ds-popover-arrow-x', arrowX);
|
|
1939
|
+
elements.floating.style.setProperty('--ds-popover-arrow-y', arrowY);
|
|
1940
|
+
return data;
|
|
1941
|
+
},
|
|
1942
|
+
};
|
|
1943
|
+
/**
|
|
1944
|
+
* @summary
|
|
1945
|
+
* Popover vises over andre elementer i grensesnittet og er koblet til et spesifikt element.
|
|
1946
|
+
* Den brukes til å vise tilleggsinformasjon, interaktive elementer eller korte forklaringer uten å navigere bort fra siden.
|
|
1947
|
+
*
|
|
1948
|
+
* @example
|
|
1949
|
+
* ```html
|
|
1950
|
+
* <button hviButton popovertarget="popover1">Open popover</button>
|
|
1951
|
+
* <hvi-popover id="popover1"> Popover content </hvi-popover>
|
|
1952
|
+
* ```
|
|
1953
|
+
*
|
|
1954
|
+
* @see {@link https://designsystemet.no/en/components/docs/popover/code}
|
|
1955
|
+
*/
|
|
1956
|
+
class HviPopover {
|
|
1957
|
+
el = inject((ElementRef));
|
|
1958
|
+
cleanupAutoUpdate;
|
|
1959
|
+
boundHandleClick;
|
|
1960
|
+
boundHandleKeydown;
|
|
1961
|
+
/** Popover type - 'manual' krever manuell lukking, 'auto' lukkes ved klikk utenfor */
|
|
1962
|
+
type = 'manual';
|
|
1963
|
+
/** Visuell variant */
|
|
1964
|
+
variant = 'default';
|
|
1965
|
+
/** Farge-tema */
|
|
1966
|
+
color = 'neutral';
|
|
1967
|
+
/** Plassering av popover relativt til trigger */
|
|
1968
|
+
placement = 'top';
|
|
1969
|
+
/** Aktiver automatisk repositjonering hvis det ikke er plass */
|
|
1970
|
+
autoPlacement = true;
|
|
1971
|
+
/** Event når popover åpnes */
|
|
1972
|
+
opened = new EventEmitter();
|
|
1973
|
+
/** Event når popover lukkes */
|
|
1974
|
+
closed = new EventEmitter();
|
|
1975
|
+
get popoverElement() {
|
|
1976
|
+
return this.el.nativeElement;
|
|
1977
|
+
}
|
|
1978
|
+
get triggerElement() {
|
|
1979
|
+
const id = this.popoverElement.id;
|
|
1980
|
+
return id ? document.querySelector(`[popovertarget="${id}"]`) : null;
|
|
1981
|
+
}
|
|
1982
|
+
ngOnInit() {
|
|
1983
|
+
this.setupEventListeners();
|
|
1984
|
+
}
|
|
1985
|
+
ngOnDestroy() {
|
|
1986
|
+
this.stopAutoUpdate();
|
|
1987
|
+
this.removeEventListeners();
|
|
1988
|
+
}
|
|
1989
|
+
setupEventListeners() {
|
|
1990
|
+
const popover = this.popoverElement;
|
|
1991
|
+
// Click utenfor lukker popover
|
|
1992
|
+
this.boundHandleClick = (event) => {
|
|
1993
|
+
const el = event.target;
|
|
1994
|
+
const isTrigger = el?.closest?.(`[popovertarget="${popover.id}"]`);
|
|
1995
|
+
const isOutside = !isTrigger && !popover.contains(el);
|
|
1996
|
+
if (isTrigger) {
|
|
1997
|
+
event.preventDefault();
|
|
1998
|
+
popover.togglePopover?.();
|
|
1999
|
+
}
|
|
2000
|
+
if (isOutside && popover.matches(':popover-open')) {
|
|
2001
|
+
popover.togglePopover?.();
|
|
2002
|
+
}
|
|
2003
|
+
};
|
|
2004
|
+
// Escape lukker popover
|
|
2005
|
+
this.boundHandleKeydown = (event) => {
|
|
2006
|
+
if (event.key !== 'Escape' || !popover.matches(':popover-open'))
|
|
2007
|
+
return;
|
|
2008
|
+
event.preventDefault();
|
|
2009
|
+
popover.togglePopover?.();
|
|
2010
|
+
};
|
|
2011
|
+
addEventListener('click', this.boundHandleClick);
|
|
2012
|
+
addEventListener('keydown', this.boundHandleKeydown);
|
|
2013
|
+
// Toggle events
|
|
2014
|
+
popover.addEventListener('beforetoggle', this.handleBeforeToggle);
|
|
2015
|
+
popover.addEventListener('toggle', this.handleToggle);
|
|
2016
|
+
}
|
|
2017
|
+
removeEventListeners() {
|
|
2018
|
+
if (this.boundHandleClick) {
|
|
2019
|
+
removeEventListener('click', this.boundHandleClick);
|
|
2020
|
+
}
|
|
2021
|
+
if (this.boundHandleKeydown) {
|
|
2022
|
+
removeEventListener('keydown', this.boundHandleKeydown);
|
|
2023
|
+
}
|
|
2024
|
+
this.popoverElement.removeEventListener('beforetoggle', this.handleBeforeToggle);
|
|
2025
|
+
this.popoverElement.removeEventListener('toggle', this.handleToggle);
|
|
2026
|
+
}
|
|
2027
|
+
handleBeforeToggle = (event) => {
|
|
2028
|
+
const toggleEvent = event;
|
|
2029
|
+
if (toggleEvent.newState === 'open') {
|
|
2030
|
+
this.updatePosition();
|
|
2031
|
+
}
|
|
2032
|
+
};
|
|
2033
|
+
handleToggle = (event) => {
|
|
2034
|
+
const toggleEvent = event;
|
|
2035
|
+
if (toggleEvent.newState === 'open') {
|
|
2036
|
+
this.startAutoUpdate();
|
|
2037
|
+
this.opened.emit();
|
|
2038
|
+
}
|
|
2039
|
+
else {
|
|
2040
|
+
this.stopAutoUpdate();
|
|
2041
|
+
this.closed.emit();
|
|
2042
|
+
}
|
|
2043
|
+
};
|
|
2044
|
+
updatePosition() {
|
|
2045
|
+
const trigger = this.triggerElement;
|
|
2046
|
+
const popover = this.popoverElement;
|
|
2047
|
+
if (!trigger || !popover)
|
|
2048
|
+
return;
|
|
2049
|
+
computePosition(trigger, popover, {
|
|
2050
|
+
placement: this.placement,
|
|
2051
|
+
strategy: 'fixed',
|
|
2052
|
+
middleware: [
|
|
2053
|
+
offset((data) => {
|
|
2054
|
+
const styles = getComputedStyle(data.elements.floating, '::before');
|
|
2055
|
+
return parseFloat(styles.height) || 12;
|
|
2056
|
+
}),
|
|
2057
|
+
...(this.autoPlacement ? [flip({ fallbackAxisSideDirection: 'start' }), shift()] : []),
|
|
2058
|
+
arrowPseudoElement,
|
|
2059
|
+
],
|
|
2060
|
+
}).then(({ x, y }) => {
|
|
2061
|
+
popover.style.translate = `${x}px ${y}px`;
|
|
2062
|
+
});
|
|
2063
|
+
}
|
|
2064
|
+
startAutoUpdate() {
|
|
2065
|
+
this.stopAutoUpdate();
|
|
2066
|
+
const trigger = this.triggerElement;
|
|
2067
|
+
const popover = this.popoverElement;
|
|
2068
|
+
if (!trigger || !popover)
|
|
2069
|
+
return;
|
|
2070
|
+
this.cleanupAutoUpdate = autoUpdate(trigger, popover, () => this.updatePosition());
|
|
2071
|
+
}
|
|
2072
|
+
stopAutoUpdate() {
|
|
2073
|
+
if (this.cleanupAutoUpdate) {
|
|
2074
|
+
this.cleanupAutoUpdate();
|
|
2075
|
+
this.cleanupAutoUpdate = undefined;
|
|
2076
|
+
}
|
|
2077
|
+
}
|
|
2078
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviPopover, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2079
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.2", type: HviPopover, isStandalone: true, selector: "hvi-popover", inputs: { type: "type", variant: "variant", color: "color", placement: "placement", autoPlacement: "autoPlacement" }, outputs: { opened: "opened", closed: "closed" }, host: { properties: { "attr.popover": "type", "attr.data-variant": "variant", "attr.data-color": "color" }, classAttribute: "ds-popover" }, ngImport: i0, template: '<ng-content />', isInline: true });
|
|
2080
|
+
}
|
|
2081
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: HviPopover, decorators: [{
|
|
2082
|
+
type: Component,
|
|
2083
|
+
args: [{
|
|
2084
|
+
selector: 'hvi-popover',
|
|
2085
|
+
standalone: true,
|
|
2086
|
+
template: '<ng-content />',
|
|
2087
|
+
host: {
|
|
2088
|
+
class: 'ds-popover',
|
|
2089
|
+
'[attr.popover]': 'type',
|
|
2090
|
+
'[attr.data-variant]': 'variant',
|
|
2091
|
+
'[attr.data-color]': 'color',
|
|
2092
|
+
},
|
|
2093
|
+
}]
|
|
2094
|
+
}], propDecorators: { type: [{
|
|
2095
|
+
type: Input
|
|
2096
|
+
}], variant: [{
|
|
2097
|
+
type: Input
|
|
2098
|
+
}], color: [{
|
|
2099
|
+
type: Input
|
|
2100
|
+
}], placement: [{
|
|
2101
|
+
type: Input
|
|
2102
|
+
}], autoPlacement: [{
|
|
2103
|
+
type: Input
|
|
2104
|
+
}], opened: [{
|
|
2105
|
+
type: Output
|
|
2106
|
+
}], closed: [{
|
|
2107
|
+
type: Output
|
|
2108
|
+
}] } });
|
|
2109
|
+
|
|
1756
2110
|
/**
|
|
1757
2111
|
* @summary
|
|
1758
2112
|
* Tag is a label that can be used to categorize items or communicate progress, status, or process. Tags can provide users with a quicker overview of content.
|
|
@@ -1803,5 +2157,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
1803
2157
|
* Generated bundle index. Do not edit.
|
|
1804
2158
|
*/
|
|
1805
2159
|
|
|
1806
|
-
export { HviAlert, HviAvatar, HviBadge, HviBadgePosition, HviBreadcrumbs, HviButton, HviCard, HviCardBlock, HviChipButton, HviChipLabel, HviControlInvalid, HviDetails, HviDetailsContent, HviDetailsSummary, HviDialog, HviDialogBlock, HviDivider, HviErrorSummary, HviField, HviFieldAffix, HviFieldAffixes, HviFieldDescription, HviFieldKit, HviFieldOptional, HviFieldValidation, HviFieldset, HviForm, HviForms, HviHeading, HviIcon, HviInput, HviLabel, HviLink, HviList, HviParagraph, HviTag, HviValidationKit, HviValidationMessage, fieldObserver, isElement, isInputLike, isLabel };
|
|
2160
|
+
export { HviAlert, HviAvatar, HviBadge, HviBadgePosition, HviBreadcrumbs, HviButton, HviCard, HviCardBlock, HviChipButton, HviChipLabel, HviControlInvalid, HviDetails, HviDetailsContent, HviDetailsSummary, HviDialog, HviDialogBlock, HviDivider, HviErrorSummary, HviField, HviFieldAffix, HviFieldAffixes, HviFieldDescription, HviFieldKit, HviFieldOptional, HviFieldValidation, HviFieldset, HviForm, HviForms, HviHeading, HviIcon, HviInput, HviLabel, HviLink, HviList, HviParagraph, HviPopover, HviTag, HviValidationKit, HviValidationMessage, fieldObserver, hviCustom, hviEmail, hviExtractMessages, hviExtractValidators, hviMax, hviMaxLength, hviMin, hviMinLength, hviNullValidator, hviPattern, hviRequired, hviRequiredTrue, hviValidators, isElement, isInputLike, isLabel };
|
|
1807
2161
|
//# sourceMappingURL=helsevestikt-hviktor-angular.mjs.map
|