@fkui/vue-labs 5.36.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.
Files changed (54) hide show
  1. package/LICENSE.md +7 -0
  2. package/README.md +3 -0
  3. package/dist/cjs/index.cjs.js +276 -0
  4. package/dist/cjs/index.cjs.js.map +1 -0
  5. package/dist/cjs/package.json +3 -0
  6. package/dist/esm/index.esm.js +258 -0
  7. package/dist/esm/index.esm.js.map +1 -0
  8. package/dist/esm/package.json +3 -0
  9. package/dist/style.css +18 -0
  10. package/dist/types/components/XSearchBar/XSearchBar.vue.d.ts +31 -0
  11. package/dist/types/components/XSearchBar/XSearchBar.vue.d.ts.map +1 -0
  12. package/dist/types/components/XSearchBar/index.d.ts +2 -0
  13. package/dist/types/components/XSearchBar/index.d.ts.map +1 -0
  14. package/dist/types/components/XTimeTextField/XTimeTextField.vue.d.ts +164 -0
  15. package/dist/types/components/XTimeTextField/XTimeTextField.vue.d.ts.map +1 -0
  16. package/dist/types/components/XTimeTextField/converters/HoursMinutesConverter.d.ts +5 -0
  17. package/dist/types/components/XTimeTextField/converters/HoursMinutesConverter.d.ts.map +1 -0
  18. package/dist/types/components/XTimeTextField/converters/index.d.ts +2 -0
  19. package/dist/types/components/XTimeTextField/converters/index.d.ts.map +1 -0
  20. package/dist/types/components/XTimeTextField/index.d.ts +5 -0
  21. package/dist/types/components/XTimeTextField/index.d.ts.map +1 -0
  22. package/dist/types/components/XTimeTextField/utils/HoursMinutesNumberUtils.d.ts +39 -0
  23. package/dist/types/components/XTimeTextField/utils/HoursMinutesNumberUtils.d.ts.map +1 -0
  24. package/dist/types/components/XTimeTextField/utils/HoursMinutesValidatorUtils.d.ts +6 -0
  25. package/dist/types/components/XTimeTextField/utils/HoursMinutesValidatorUtils.d.ts.map +1 -0
  26. package/dist/types/components/XTimeTextField/utils/constants.d.ts +3 -0
  27. package/dist/types/components/XTimeTextField/utils/constants.d.ts.map +1 -0
  28. package/dist/types/components/XTimeTextField/utils/index.d.ts +4 -0
  29. package/dist/types/components/XTimeTextField/utils/index.d.ts.map +1 -0
  30. package/dist/types/components/XTimeTextField/validators/GreaterThanTimeValidator.d.ts +3 -0
  31. package/dist/types/components/XTimeTextField/validators/GreaterThanTimeValidator.d.ts.map +1 -0
  32. package/dist/types/components/XTimeTextField/validators/HoursMinutesValidator.d.ts +3 -0
  33. package/dist/types/components/XTimeTextField/validators/HoursMinutesValidator.d.ts.map +1 -0
  34. package/dist/types/components/XTimeTextField/validators/LessThanTimeValidator.d.ts +3 -0
  35. package/dist/types/components/XTimeTextField/validators/LessThanTimeValidator.d.ts.map +1 -0
  36. package/dist/types/components/XTimeTextField/validators/MaxTimeValidator.d.ts +3 -0
  37. package/dist/types/components/XTimeTextField/validators/MaxTimeValidator.d.ts.map +1 -0
  38. package/dist/types/components/XTimeTextField/validators/MinTimeValidator.d.ts +3 -0
  39. package/dist/types/components/XTimeTextField/validators/MinTimeValidator.d.ts.map +1 -0
  40. package/dist/types/components/XTimeTextField/validators/index.d.ts +2 -0
  41. package/dist/types/components/XTimeTextField/validators/index.d.ts.map +1 -0
  42. package/dist/types/components/index.d.ts +3 -0
  43. package/dist/types/components/index.d.ts.map +1 -0
  44. package/dist/types/index.d.ts +2 -0
  45. package/dist/types/index.d.ts.map +1 -0
  46. package/dist/types/local.d.ts +7 -0
  47. package/dist/types/local.d.ts.map +1 -0
  48. package/dist/types/vite-dev/app.vue.d.ts +5 -0
  49. package/dist/types/vite-dev/app.vue.d.ts.map +1 -0
  50. package/package.json +97 -0
  51. package/pageobject/XDummy.pageobject.d.ts +14 -0
  52. package/pageobject/common.d.ts +13 -0
  53. package/pageobject/index.d.ts +2 -0
  54. package/pageobject/trimmedText.d.ts +28 -0
package/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2021 Försäkringskassan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # fkui/vue-labs
2
+
3
+ Detta repo innehåller experimentversioner av komponenter och annan funktionalitet. Komponenterna är inte fullt ut testade, såväl enhetstest som tillgängligthet och SLA kan saknas. Konsumenten ansvarar för att själv testa komponenten. Komponenter i labs kan förändras och även försvinna.
@@ -0,0 +1,276 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, Symbol.toStringTag, {
4
+ value: "Module"
5
+ });
6
+ const logic = require("@fkui/logic");
7
+ const vue = require("vue");
8
+ const vue$1 = require("@fkui/vue");
9
+ const HOURS_MINUTES_REGEXP = /^(?<hours>[0-9]+)?(:(?<minutes>[0-5][0-9]))?$/;
10
+ const HOURS_MINUTES_WITHOUT_COLON_REGEXP = /^(?<hours>[0-9]{2})(?<minutes>[0-5][0-9])$/;
11
+ function findMatch(regexps, value) {
12
+ for (const regexp of regexps) {
13
+ const match = value.match(regexp);
14
+ if (match) {
15
+ return match;
16
+ }
17
+ }
18
+ return null;
19
+ }
20
+ function padInitialZeros(value, maxLength = 2) {
21
+ var _value;
22
+ value = (_value = value) !== null && _value !== void 0 ? _value : "";
23
+ return value.padStart(maxLength, "0");
24
+ }
25
+ function hoursMinutesStringToMinutes(valueString, extraForgiving = false) {
26
+ if (logic.isEmpty(valueString.trim())) {
27
+ return void 0;
28
+ }
29
+ const [hours, minutes] = splitHoursMinutes(valueString, extraForgiving).map(value => parseInt(value, 10));
30
+ const totalMinutes = hours * 60 + minutes;
31
+ return !isNaN(totalMinutes) ? totalMinutes : void 0;
32
+ }
33
+ function minutesToHoursMinutesString(value) {
34
+ let valueString = "";
35
+ const safeValue = value !== null && value !== void 0 ? value : NaN;
36
+ if (!isNaN(safeValue)) {
37
+ const {
38
+ hours,
39
+ minutes
40
+ } = minutesToObject(safeValue);
41
+ valueString = [hours, minutes].map(value2 => String(value2).padStart(2, "0")).join(":");
42
+ }
43
+ return logic.stripWhitespace(valueString);
44
+ }
45
+ function splitHoursMinutes(valueString, extraForgiving = false) {
46
+ var _a, _b;
47
+ const regexps = extraForgiving ? [HOURS_MINUTES_WITHOUT_COLON_REGEXP, HOURS_MINUTES_REGEXP] : [HOURS_MINUTES_REGEXP];
48
+ const match = findMatch(regexps, logic.stripWhitespace(valueString));
49
+ if (!match) {
50
+ return ["", ""];
51
+ }
52
+ const hours = padInitialZeros((_a = match == null ? void 0 : match.groups) == null ? void 0 : _a.hours);
53
+ const minutes = padInitialZeros((_b = match == null ? void 0 : match.groups) == null ? void 0 : _b.minutes);
54
+ return [hours, minutes];
55
+ }
56
+ function minutesToUserFriendlyString(value) {
57
+ const [hours, minutes] = splitHoursMinutes(minutesToHoursMinutesString(value)).map(Number);
58
+ return logic.TranslationService.provider.translate("ARBE.RW.generell.etikett.timmarochminuter", "{{hours}} timmar och {{minutes}} minuter", {
59
+ hours,
60
+ minutes
61
+ });
62
+ }
63
+ function minutesToHoursFloat(...values) {
64
+ const minutes = values.filter(value => logic.isSet(value) && !isNaN(value)).reduce((sum, value) => sum + value, 0);
65
+ return minutes / 60;
66
+ }
67
+ function minutesToObject(...values) {
68
+ const minutes = values.filter(value => logic.isSet(value) && !isNaN(value)).reduce((sum, value) => sum + value, 0);
69
+ return {
70
+ hours: Math.floor(minutes / 60),
71
+ minutes: minutes % 60
72
+ };
73
+ }
74
+ function formatNumberToTime(value) {
75
+ if (typeof value !== "number" || isNaN(value)) {
76
+ return void 0;
77
+ }
78
+ return minutesToHoursMinutesString(value);
79
+ }
80
+ function parseTimeToNumberUsingConfig(value, extraForgiving) {
81
+ var _hoursMinutesStringTo;
82
+ if (typeof value !== "string") {
83
+ return void 0;
84
+ }
85
+ const parsedValue = (_hoursMinutesStringTo = hoursMinutesStringToMinutes(value, extraForgiving)) !== null && _hoursMinutesStringTo !== void 0 ? _hoursMinutesStringTo : NaN;
86
+ return !isNaN(parsedValue) ? parsedValue : void 0;
87
+ }
88
+ function parseTimeToNumber(value) {
89
+ return parseTimeToNumberUsingConfig(value, false);
90
+ }
91
+ function forgivingParseTimeToNumber(value) {
92
+ return parseTimeToNumberUsingConfig(value, true);
93
+ }
94
+ class HoursMinutesValidatorUtils {
95
+ static validate(value, config, name, compare) {
96
+ if (value === "") {
97
+ return true;
98
+ }
99
+ const limit = config[name];
100
+ if (!logic.isSet(limit)) {
101
+ return false;
102
+ }
103
+ const parseFunction = HoursMinutesValidatorUtils.getParserFromConfig(config);
104
+ const limitAsNumber = parseFunction(String(config[name]));
105
+ if (!logic.isSet(limitAsNumber)) {
106
+ throw new Error(`config.${name} must be a number`);
107
+ }
108
+ const valueAsNumber = parseFunction(value);
109
+ if (!logic.isSet(valueAsNumber)) {
110
+ return false;
111
+ }
112
+ return compare(valueAsNumber, limitAsNumber);
113
+ }
114
+ static getParserFromConfig(config) {
115
+ var _a;
116
+ if (!logic.isSet(config) || !Array.isArray(config.parser) || !logic.isSet((_a = config.parser) == null ? void 0 : _a[0]) || typeof config.parser[0] !== "function") {
117
+ return parseTimeToNumber;
118
+ }
119
+ return config.parser[0];
120
+ }
121
+ }
122
+ const hoursMinutesValidator = {
123
+ name: "hoursMinutes",
124
+ validation(value, _element, config) {
125
+ return logic.isEmpty(value) || logic.isSet(HoursMinutesValidatorUtils.getParserFromConfig(config)(value));
126
+ }
127
+ };
128
+ const greaterThanTimeValidator = {
129
+ name: "greaterThanTime",
130
+ validation(value, _element, config) {
131
+ return HoursMinutesValidatorUtils.validate(value, config, "limit", (value2, limit) => {
132
+ return value2 > limit;
133
+ });
134
+ }
135
+ };
136
+ const lessThanTimeValidator = {
137
+ name: "lessThanTime",
138
+ validation(value, _element, config) {
139
+ return HoursMinutesValidatorUtils.validate(value, config, "limit", (value2, limit) => {
140
+ return value2 < limit;
141
+ });
142
+ }
143
+ };
144
+ const maxTimeValidator = {
145
+ name: "maxTime",
146
+ validation(value, _element, config) {
147
+ return HoursMinutesValidatorUtils.validate(value, config, this.name, (value2, limit) => {
148
+ return value2 <= limit;
149
+ });
150
+ }
151
+ };
152
+ const minTimeValidator = {
153
+ name: "minTime",
154
+ validation(value, _element, config) {
155
+ return HoursMinutesValidatorUtils.validate(value, config, this.name, (value2, limit) => {
156
+ return value2 >= limit;
157
+ });
158
+ }
159
+ };
160
+ const validators = [hoursMinutesValidator, greaterThanTimeValidator, lessThanTimeValidator, maxTimeValidator, minTimeValidator];
161
+ for (const validator of validators) {
162
+ logic.ValidationService.registerValidator(validator);
163
+ }
164
+ const _sfc_main$1 = vue.defineComponent({
165
+ name: "XTimeTextField",
166
+ extends: vue$1.FTextField,
167
+ mixins: [vue$1.TranslationMixin],
168
+ props: {
169
+ formatter: {
170
+ type: Function,
171
+ required: false,
172
+ default: formatNumberToTime
173
+ },
174
+ parser: {
175
+ type: Function,
176
+ required: false,
177
+ default: parseTimeToNumber
178
+ }
179
+ },
180
+ setup() {
181
+ return {
182
+ textFieldTableMode: vue.inject("textFieldTableMode", false)
183
+ };
184
+ },
185
+ mounted() {
186
+ const inputElement = this.$el.querySelector("input");
187
+ if (!logic.isSet(inputElement)) {
188
+ throw new Error(`Could not find input element in XTimeTextField with id ${this.$el.id}`);
189
+ }
190
+ logic.ValidationService.addValidatorsToElement(inputElement, {
191
+ maxLength: {
192
+ length: 10
193
+ },
194
+ hoursMinutes: {}
195
+ }, true);
196
+ inputElement.setAttribute("inputmode", "numeric");
197
+ logic.ValidationService.validateElement(inputElement);
198
+ }
199
+ });
200
+ const _sfc_main = vue.defineComponent({
201
+ name: "XSearchBar",
202
+ components: {
203
+ FIcon: vue$1.FIcon,
204
+ FSearchTextField: vue$1.FSearchTextField
205
+ },
206
+ props: {
207
+ modelValue: {
208
+ type: String,
209
+ required: true
210
+ },
211
+ maxLength: {
212
+ type: Number,
213
+ default: 20
214
+ }
215
+ },
216
+ emits: ["update:modelValue", "changedValue"],
217
+ computed: {
218
+ value: {
219
+ get() {
220
+ return this.modelValue;
221
+ },
222
+ set(value) {
223
+ if (this.value !== value) {
224
+ this.$emit("changedValue", [this.value, value]);
225
+ }
226
+ this.$emit("update:modelValue", value);
227
+ }
228
+ }
229
+ }
230
+ });
231
+ const _export_sfc = (sfc, props) => {
232
+ const target = sfc.__vccOpts || sfc;
233
+ for (const [key, val] of props) {
234
+ target[key] = val;
235
+ }
236
+ return target;
237
+ };
238
+ const _hoisted_1 = {
239
+ class: "button button--primary search-bar-button",
240
+ type: "submit",
241
+ "data-test": "search-bar-submit"
242
+ };
243
+ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
244
+ const _component_f_icon = vue.resolveComponent("f-icon");
245
+ const _component_f_search_text_field = vue.resolveComponent("f-search-text-field");
246
+ return vue.openBlock(), vue.createBlock(_component_f_search_text_field, {
247
+ modelValue: _ctx.value,
248
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => _ctx.value = $event),
249
+ class: "x-search-bar",
250
+ maxlength: _ctx.maxLength
251
+ }, {
252
+ default: vue.withCtx(() => [vue.renderSlot(_ctx.$slots, "default")]),
253
+ tooltip: vue.withCtx(() => [vue.renderSlot(_ctx.$slots, "tooltip")]),
254
+ "input-right": vue.withCtx(() => [vue.createElementVNode("button", _hoisted_1, [vue.createVNode(_component_f_icon, {
255
+ name: "search",
256
+ library: "f"
257
+ }), vue.createTextVNode(), vue.createElementVNode("span", null, [vue.renderSlot(_ctx.$slots, "button-text", {}, () => [vue.createTextVNode(" Sök ")])])])]),
258
+ _: 3
259
+ /* FORWARDED */
260
+ }, 8, ["modelValue", "maxlength"]);
261
+ }
262
+ const XSearchBar = /* @__PURE__ */_export_sfc(_sfc_main, [["render", _sfc_render]]);
263
+ exports.HOURS_MINUTES_REGEXP = HOURS_MINUTES_REGEXP;
264
+ exports.HOURS_MINUTES_WITHOUT_COLON_REGEXP = HOURS_MINUTES_WITHOUT_COLON_REGEXP;
265
+ exports.HoursMinutesValidatorUtils = HoursMinutesValidatorUtils;
266
+ exports.XSearchBar = XSearchBar;
267
+ exports.XTimeTextField = _sfc_main$1;
268
+ exports.forgivingParseTimeToNumber = forgivingParseTimeToNumber;
269
+ exports.formatNumberToTime = formatNumberToTime;
270
+ exports.hoursMinutesStringToMinutes = hoursMinutesStringToMinutes;
271
+ exports.minutesToHoursFloat = minutesToHoursFloat;
272
+ exports.minutesToHoursMinutesString = minutesToHoursMinutesString;
273
+ exports.minutesToObject = minutesToObject;
274
+ exports.minutesToUserFriendlyString = minutesToUserFriendlyString;
275
+ exports.parseTimeToNumber = parseTimeToNumber;
276
+ exports.splitHoursMinutes = splitHoursMinutes;
@@ -0,0 +1 @@
1
+ {"version":3,"names":["HOURS_MINUTES_REGEXP","HOURS_MINUTES_WITHOUT_COLON_REGEXP","findMatch","regexps","value","regexp","match","padInitialZeros","maxLength","_value","padStart","hoursMinutesStringToMinutes","valueString","extraForgiving","logic","isEmpty","trim","hours","minutes","splitHoursMinutes","map","parseInt","totalMinutes","isNaN","minutesToHoursMinutesString","safeValue","NaN","minutesToObject","value2","String","join","stripWhitespace","_a","groups","_b","minutesToUserFriendlyString","Number","TranslationService","provider","translate","minutesToHoursFloat","values","filter","isSet","reduce","sum","Math","floor","formatNumberToTime","parseTimeToNumberUsingConfig","_hoursMinutesStringTo","parsedValue","parseTimeToNumber","forgivingParseTimeToNumber","HoursMinutesValidatorUtils","validate","config","name","compare","limit","parseFunction","getParserFromConfig","limitAsNumber","Error","valueAsNumber","Array","isArray","parser","hoursMinutesValidator","validation","_element","greaterThanTimeValidator","lessThanTimeValidator","maxTimeValidator","minTimeValidator","validators","validator","ValidationService","registerValidator","_sfc_main$1","vue","defineComponent","extends","vue$1","FTextField","mixins","TranslationMixin","props","formatter","type","Function","required","default","setup","textFieldTableMode","inject","mounted","inputElement","$el","querySelector","id","addValidatorsToElement","length","hoursMinutes","setAttribute","validateElement","_sfc_main","components","FIcon","FSearchTextField","modelValue","emits","computed","get","set","$emit","_hoisted_1","class","_component_f_search_text_field","resolveComponent","openBlock","createBlock","_ctx","_cache","$event","maxlength","withCtx","renderSlot","$slots","tooltip","createElementVNode","createVNode","_component_f_icon","library","createTextVNode","_"],"sources":["../src/components/XTimeTextField/utils/constants.ts","../src/components/XTimeTextField/utils/HoursMinutesNumberUtils.ts","../src/components/XTimeTextField/converters/HoursMinutesConverter.ts","../src/components/XTimeTextField/utils/HoursMinutesValidatorUtils.ts","../src/components/XTimeTextField/validators/HoursMinutesValidator.ts","../src/components/XTimeTextField/validators/GreaterThanTimeValidator.ts","../src/components/XTimeTextField/validators/LessThanTimeValidator.ts","../src/components/XTimeTextField/validators/MaxTimeValidator.ts","../src/components/XTimeTextField/validators/MinTimeValidator.ts","../src/components/XTimeTextField/validators/index.ts","../src/components/XTimeTextField/XTimeTextField.vue","../src/components/XSearchBar/XSearchBar.vue"],"sourcesContent":["export const HOURS_MINUTES_REGEXP =\n /^(?<hours>[0-9]+)?(:(?<minutes>[0-5][0-9]))?$/;\nexport const HOURS_MINUTES_WITHOUT_COLON_REGEXP =\n /^(?<hours>[0-9]{2})(?<minutes>[0-5][0-9])$/;\n","import {\n TranslationService,\n isEmpty,\n isSet,\n stripWhitespace,\n} from \"@fkui/logic\";\nimport { HoursMinutesString } from \"../converters\";\nimport {\n HOURS_MINUTES_REGEXP,\n HOURS_MINUTES_WITHOUT_COLON_REGEXP,\n} from \"./constants\";\n\nfunction findMatch(regexps: RegExp[], value: string): RegExpMatchArray | null {\n for (const regexp of regexps) {\n const match = value.match(regexp);\n\n if (match) {\n return match;\n }\n }\n\n return null;\n}\n\nfunction padInitialZeros(value: string | undefined, maxLength = 2): string {\n value = value ?? \"\";\n return value.padStart(maxLength, \"0\");\n}\n\nexport function hoursMinutesStringToMinutes(\n valueString: string,\n extraForgiving = false,\n): number | undefined {\n if (isEmpty(valueString.trim())) {\n return undefined;\n }\n\n const [hours, minutes] = splitHoursMinutes(valueString, extraForgiving).map(\n (value) => parseInt(value, 10),\n );\n const totalMinutes = hours * 60 + minutes;\n\n return !isNaN(totalMinutes) ? totalMinutes : undefined;\n}\n\nexport function minutesToHoursMinutesString(\n value?: number,\n): HoursMinutesString {\n let valueString = \"\";\n const safeValue = value ?? NaN;\n if (!isNaN(safeValue)) {\n const { hours, minutes } = minutesToObject(safeValue);\n valueString = [hours, minutes]\n .map((value) => String(value).padStart(2, \"0\"))\n .join(\":\");\n }\n\n return stripWhitespace(valueString);\n}\n\nexport function splitHoursMinutes(\n valueString: string,\n extraForgiving = false,\n): string[] {\n const regexps = extraForgiving\n ? [HOURS_MINUTES_WITHOUT_COLON_REGEXP, HOURS_MINUTES_REGEXP]\n : [HOURS_MINUTES_REGEXP];\n const match = findMatch(regexps, stripWhitespace(valueString));\n\n if (!match) {\n return [\"\", \"\"];\n }\n\n const hours = padInitialZeros(match?.groups?.hours);\n const minutes = padInitialZeros(match?.groups?.minutes);\n\n return [hours, minutes];\n}\n\n/**\n * Accepts time as a number and returns a user friendly string (to be used in i.e. review mode)\n * Example:\n * Input: 13.5\n * Output: '13 timmar och 30 minuter'\n */\nexport function minutesToUserFriendlyString(value: number): string {\n const [hours, minutes] = splitHoursMinutes(\n minutesToHoursMinutesString(value),\n ).map(Number);\n\n return TranslationService.provider.translate(\n \"ARBE.RW.generell.etikett.timmarochminuter\",\n \"{{hours}} timmar och {{minutes}} minuter\",\n { hours, minutes },\n );\n}\n\n/**\n * Helper for converting AgeTimeTextField values into hours. For convienence,\n * it is possible to provide multiple values and get their sum. The actual\n * conversion will be performed as a last step, to minimize the amount of rounding\n * errors.\n *\n * Parameters that are undefined or NaN will be ignored and add 0 to the sum.\n *\n * @param values - Values in minutes, to be converted into a value in hours.\n * @returns The sum of all values divided by 60. E.g., `150` becomes `2.5`.\n */\nexport function minutesToHoursFloat(\n ...values: Array<number | undefined>\n): number {\n const minutes = values\n .filter((value): value is number => isSet(value) && !isNaN(value))\n .reduce((sum, value) => sum + value, 0);\n\n return minutes / 60;\n}\n\n/**\n * Helper for converting AgeTimeTextField values into an object. For\n * convenience, it is possible to provide multiple values and get their sum.\n *\n * Parameters that are undefined or NaN will be ignored and add 0 to the sum.\n *\n * @param values - Values in minutes, to be converted into a value into an\n * hour minute object.\n * @returns The sum of all values in an object representation. E.g.,\n * `150` becomes `{ hours: 2, minutes: 30 }`\n */\nexport function minutesToObject(...values: Array<number | undefined>): {\n hours: number;\n minutes: number;\n} {\n const minutes = values\n .filter((value): value is number => isSet(value) && !isNaN(value))\n .reduce((sum, value) => sum + value, 0);\n\n return {\n hours: Math.floor(minutes / 60),\n minutes: minutes % 60,\n };\n}\n","import {\n minutesToHoursMinutesString,\n hoursMinutesStringToMinutes,\n} from \"../utils\";\n\n// A string in the format hh:mm (hours may exceed two digits), e.g., 08:15, 16:00 and 900:12.\nexport type HoursMinutesString = string;\n\nexport function formatNumberToTime(\n value?: number,\n): HoursMinutesString | undefined {\n if (typeof value !== \"number\" || isNaN(value)) {\n return undefined;\n }\n\n return minutesToHoursMinutesString(value);\n}\n\nfunction parseTimeToNumberUsingConfig(\n value: string | null | undefined,\n extraForgiving: boolean,\n): number | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const parsedValue =\n hoursMinutesStringToMinutes(value, extraForgiving) ?? NaN;\n\n return !isNaN(parsedValue) ? parsedValue : undefined;\n}\n\nexport function parseTimeToNumber(value?: string | null): number | undefined {\n return parseTimeToNumberUsingConfig(value, false);\n}\n\nexport function forgivingParseTimeToNumber(\n value?: string | null,\n): number | undefined {\n return parseTimeToNumberUsingConfig(value, true);\n}\n","import { type ValidatorConfig, isSet } from \"@fkui/logic\";\nimport { parseTimeToNumber } from \"../converters\";\n\n/* eslint-disable-next-line @typescript-eslint/no-extraneous-class -- technical\n * debt, should be refactored to vanilla functions */\nexport class HoursMinutesValidatorUtils {\n public static validate(\n value: string,\n config: ValidatorConfig,\n name: string,\n compare: (value: number, limit: number) => boolean,\n ): boolean {\n if (value === \"\") {\n return true;\n }\n\n const limit = config[name];\n if (!isSet(limit)) {\n return false;\n }\n\n const parseFunction =\n HoursMinutesValidatorUtils.getParserFromConfig(config);\n const limitAsNumber = parseFunction(String(config[name]));\n if (!isSet(limitAsNumber)) {\n throw new Error(`config.${name} must be a number`);\n }\n\n const valueAsNumber = parseFunction(value);\n if (!isSet(valueAsNumber)) {\n return false;\n }\n\n return compare(valueAsNumber, limitAsNumber);\n }\n\n public static getParserFromConfig(\n config?: ValidatorConfig,\n ): (viewValue: string | null | undefined) => number | undefined {\n if (\n !isSet(config) ||\n !Array.isArray(config.parser) ||\n !isSet(config.parser?.[0]) ||\n typeof config.parser[0] !== \"function\"\n ) {\n return parseTimeToNumber;\n }\n\n return config.parser[0] as (\n viewValue: string | null | undefined,\n ) => number | undefined;\n }\n}\n","import {\n type ValidatableHTMLElement,\n type Validator,\n type ValidatorName,\n type ValidatorConfig,\n isEmpty,\n isSet,\n} from \"@fkui/logic\";\nimport { HoursMinutesValidatorUtils } from \"../utils\";\n\nexport const hoursMinutesValidator: Validator = {\n name: \"hoursMinutes\" as ValidatorName,\n validation(\n value: string,\n _element: ValidatableHTMLElement,\n config: ValidatorConfig,\n ): boolean {\n return (\n isEmpty(value) ||\n isSet(HoursMinutesValidatorUtils.getParserFromConfig(config)(value))\n );\n },\n};\n","import {\n type Validator,\n type ValidatorName,\n type ValidatableHTMLElement,\n type ValidatorConfig,\n} from \"@fkui/logic\";\nimport { HoursMinutesValidatorUtils } from \"../utils\";\n\nexport const greaterThanTimeValidator: Validator = {\n name: \"greaterThanTime\" as ValidatorName,\n validation(\n value: string,\n _element: ValidatableHTMLElement,\n config: ValidatorConfig,\n ): boolean {\n return HoursMinutesValidatorUtils.validate(\n value,\n config,\n \"limit\",\n (value: number, limit: number) => {\n return value > limit;\n },\n );\n },\n};\n","import {\n type Validator,\n type ValidatorName,\n type ValidatableHTMLElement,\n type ValidatorConfig,\n} from \"@fkui/logic\";\nimport { HoursMinutesValidatorUtils } from \"../utils\";\n\nexport const lessThanTimeValidator: Validator = {\n name: \"lessThanTime\" as ValidatorName,\n validation(\n value: string,\n _element: ValidatableHTMLElement,\n config: ValidatorConfig,\n ): boolean {\n return HoursMinutesValidatorUtils.validate(\n value,\n config,\n \"limit\",\n (value: number, limit: number) => {\n return value < limit;\n },\n );\n },\n};\n","import {\n type Validator,\n type ValidatorName,\n type ValidatableHTMLElement,\n type ValidatorConfig,\n} from \"@fkui/logic\";\nimport { HoursMinutesValidatorUtils } from \"../utils\";\n\nexport const maxTimeValidator: Validator = {\n name: \"maxTime\" as ValidatorName,\n validation(\n value: string,\n _element: ValidatableHTMLElement,\n config: ValidatorConfig,\n ): boolean {\n return HoursMinutesValidatorUtils.validate(\n value,\n config,\n this.name,\n (value: number, limit: number) => {\n return value <= limit;\n },\n );\n },\n};\n","import {\n type Validator,\n type ValidatorName,\n type ValidatorConfig,\n type ValidatableHTMLElement,\n} from \"@fkui/logic\";\nimport { HoursMinutesValidatorUtils } from \"../utils\";\n\nexport const minTimeValidator: Validator = {\n name: \"minTime\" as ValidatorName,\n validation(\n value: string,\n _element: ValidatableHTMLElement,\n config: ValidatorConfig,\n ): boolean {\n return HoursMinutesValidatorUtils.validate(\n value,\n config,\n this.name,\n (value: number, limit: number) => {\n return value >= limit;\n },\n );\n },\n};\n","import { ValidationService, type Validator } from \"@fkui/logic\";\nimport { hoursMinutesValidator } from \"./HoursMinutesValidator\";\nimport { greaterThanTimeValidator } from \"./GreaterThanTimeValidator\";\nimport { lessThanTimeValidator } from \"./LessThanTimeValidator\";\nimport { maxTimeValidator } from \"./MaxTimeValidator\";\nimport { minTimeValidator } from \"./MinTimeValidator\";\n\nconst validators: Validator[] = [\n hoursMinutesValidator,\n greaterThanTimeValidator,\n lessThanTimeValidator,\n maxTimeValidator,\n minTimeValidator,\n];\n\nfor (const validator of validators) {\n ValidationService.registerValidator(validator);\n}\n","<script lang=\"ts\">\nimport { type PropType, defineComponent, inject } from \"vue\";\nimport { FTextField, TranslationMixin, type ParseFunction, type FormatFunction } from \"@fkui/vue\";\nimport { isSet, ValidationService } from \"@fkui/logic\";\nimport { HoursMinutesString, formatNumberToTime, parseTimeToNumber } from \"./converters\";\nimport \"./validators\";\n\nexport default defineComponent({\n name: \"XTimeTextField\",\n extends: FTextField,\n mixins: [TranslationMixin],\n props: {\n formatter: {\n type: Function as PropType<FormatFunction<HoursMinutesString>>,\n required: false,\n default: formatNumberToTime,\n },\n parser: {\n type: Function as PropType<ParseFunction<number>>,\n required: false,\n default: parseTimeToNumber,\n },\n },\n setup() {\n return {\n textFieldTableMode: inject(\"textFieldTableMode\", false) as boolean,\n };\n },\n mounted() {\n const inputElement: HTMLInputElement = this.$el.querySelector(\"input\");\n\n if (!isSet(inputElement)) {\n throw new Error(`Could not find input element in XTimeTextField with id ${this.$el.id}`);\n }\n\n ValidationService.addValidatorsToElement(\n inputElement,\n {\n maxLength: { length: 10 },\n hoursMinutes: {},\n },\n true,\n );\n\n inputElement.setAttribute(\"inputmode\", \"numeric\");\n\n ValidationService.validateElement(inputElement);\n },\n});\n</script>\n","<template>\n <f-search-text-field v-model=\"value\" class=\"x-search-bar\" :maxlength=\"maxLength\">\n <template #default>\n <!-- @slot Slot for input label -->\n <slot></slot>\n </template>\n <template #tooltip>\n <!-- @slot Slot for tooltip -->\n <slot name=\"tooltip\"></slot>\n </template>\n <template #input-right>\n <button class=\"button button--primary search-bar-button\" type=\"submit\" data-test=\"search-bar-submit\">\n <f-icon name=\"search\" library=\"f\"></f-icon>\n <span>\n <!-- @slot Slot for text in button -->\n <slot name=\"button-text\"> Sök </slot>\n </span>\n </button>\n </template>\n </f-search-text-field>\n</template>\n<script lang=\"ts\">\nimport { FIcon, FSearchTextField } from \"@fkui/vue\";\nimport { defineComponent } from \"vue\";\n\nexport default defineComponent({\n name: \"XSearchBar\",\n components: {\n FIcon,\n FSearchTextField,\n },\n props: {\n modelValue: {\n type: String,\n required: true,\n },\n maxLength: {\n type: Number,\n default: 20,\n },\n },\n emits: [\"update:modelValue\", \"changedValue\"],\n computed: {\n value: {\n get() {\n return this.modelValue;\n },\n set(value: string) {\n if (this.value !== value) {\n /**\n * Event that is dispatched when the value is changed and differs from the previous value.\n *\n * @event changedValue\n */\n this.$emit(\"changedValue\", [this.value, value]);\n }\n /**\n * V-model event.\n *\n * @event update:modelValue\n * @type {string}\n */\n this.$emit(\"update:modelValue\", value);\n },\n },\n },\n});\n</script>\n<style lang=\"scss\">\n@import \"./XSearchBar.scss\";\n</style>\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,258 @@
1
+ import { isEmpty, stripWhitespace, TranslationService, isSet, ValidationService } from "@fkui/logic";
2
+ import { defineComponent, inject, resolveComponent, openBlock, createBlock, withCtx, renderSlot, createElementVNode, createVNode, createTextVNode } from "vue";
3
+ import { FTextField, TranslationMixin, FIcon, FSearchTextField } from "@fkui/vue";
4
+ const HOURS_MINUTES_REGEXP = /^(?<hours>[0-9]+)?(:(?<minutes>[0-5][0-9]))?$/;
5
+ const HOURS_MINUTES_WITHOUT_COLON_REGEXP = /^(?<hours>[0-9]{2})(?<minutes>[0-5][0-9])$/;
6
+ function findMatch(regexps, value) {
7
+ for (const regexp of regexps) {
8
+ const match = value.match(regexp);
9
+ if (match) {
10
+ return match;
11
+ }
12
+ }
13
+ return null;
14
+ }
15
+ function padInitialZeros(value, maxLength = 2) {
16
+ var _value;
17
+ value = (_value = value) !== null && _value !== void 0 ? _value : "";
18
+ return value.padStart(maxLength, "0");
19
+ }
20
+ function hoursMinutesStringToMinutes(valueString, extraForgiving = false) {
21
+ if (isEmpty(valueString.trim())) {
22
+ return void 0;
23
+ }
24
+ const [hours, minutes] = splitHoursMinutes(valueString, extraForgiving).map(value => parseInt(value, 10));
25
+ const totalMinutes = hours * 60 + minutes;
26
+ return !isNaN(totalMinutes) ? totalMinutes : void 0;
27
+ }
28
+ function minutesToHoursMinutesString(value) {
29
+ let valueString = "";
30
+ const safeValue = value !== null && value !== void 0 ? value : NaN;
31
+ if (!isNaN(safeValue)) {
32
+ const {
33
+ hours,
34
+ minutes
35
+ } = minutesToObject(safeValue);
36
+ valueString = [hours, minutes].map(value2 => String(value2).padStart(2, "0")).join(":");
37
+ }
38
+ return stripWhitespace(valueString);
39
+ }
40
+ function splitHoursMinutes(valueString, extraForgiving = false) {
41
+ var _a, _b;
42
+ const regexps = extraForgiving ? [HOURS_MINUTES_WITHOUT_COLON_REGEXP, HOURS_MINUTES_REGEXP] : [HOURS_MINUTES_REGEXP];
43
+ const match = findMatch(regexps, stripWhitespace(valueString));
44
+ if (!match) {
45
+ return ["", ""];
46
+ }
47
+ const hours = padInitialZeros((_a = match == null ? void 0 : match.groups) == null ? void 0 : _a.hours);
48
+ const minutes = padInitialZeros((_b = match == null ? void 0 : match.groups) == null ? void 0 : _b.minutes);
49
+ return [hours, minutes];
50
+ }
51
+ function minutesToUserFriendlyString(value) {
52
+ const [hours, minutes] = splitHoursMinutes(minutesToHoursMinutesString(value)).map(Number);
53
+ return TranslationService.provider.translate("ARBE.RW.generell.etikett.timmarochminuter", "{{hours}} timmar och {{minutes}} minuter", {
54
+ hours,
55
+ minutes
56
+ });
57
+ }
58
+ function minutesToHoursFloat(...values) {
59
+ const minutes = values.filter(value => isSet(value) && !isNaN(value)).reduce((sum, value) => sum + value, 0);
60
+ return minutes / 60;
61
+ }
62
+ function minutesToObject(...values) {
63
+ const minutes = values.filter(value => isSet(value) && !isNaN(value)).reduce((sum, value) => sum + value, 0);
64
+ return {
65
+ hours: Math.floor(minutes / 60),
66
+ minutes: minutes % 60
67
+ };
68
+ }
69
+ function formatNumberToTime(value) {
70
+ if (typeof value !== "number" || isNaN(value)) {
71
+ return void 0;
72
+ }
73
+ return minutesToHoursMinutesString(value);
74
+ }
75
+ function parseTimeToNumberUsingConfig(value, extraForgiving) {
76
+ var _hoursMinutesStringTo;
77
+ if (typeof value !== "string") {
78
+ return void 0;
79
+ }
80
+ const parsedValue = (_hoursMinutesStringTo = hoursMinutesStringToMinutes(value, extraForgiving)) !== null && _hoursMinutesStringTo !== void 0 ? _hoursMinutesStringTo : NaN;
81
+ return !isNaN(parsedValue) ? parsedValue : void 0;
82
+ }
83
+ function parseTimeToNumber(value) {
84
+ return parseTimeToNumberUsingConfig(value, false);
85
+ }
86
+ function forgivingParseTimeToNumber(value) {
87
+ return parseTimeToNumberUsingConfig(value, true);
88
+ }
89
+ class HoursMinutesValidatorUtils {
90
+ static validate(value, config, name, compare) {
91
+ if (value === "") {
92
+ return true;
93
+ }
94
+ const limit = config[name];
95
+ if (!isSet(limit)) {
96
+ return false;
97
+ }
98
+ const parseFunction = HoursMinutesValidatorUtils.getParserFromConfig(config);
99
+ const limitAsNumber = parseFunction(String(config[name]));
100
+ if (!isSet(limitAsNumber)) {
101
+ throw new Error(`config.${name} must be a number`);
102
+ }
103
+ const valueAsNumber = parseFunction(value);
104
+ if (!isSet(valueAsNumber)) {
105
+ return false;
106
+ }
107
+ return compare(valueAsNumber, limitAsNumber);
108
+ }
109
+ static getParserFromConfig(config) {
110
+ var _a;
111
+ if (!isSet(config) || !Array.isArray(config.parser) || !isSet((_a = config.parser) == null ? void 0 : _a[0]) || typeof config.parser[0] !== "function") {
112
+ return parseTimeToNumber;
113
+ }
114
+ return config.parser[0];
115
+ }
116
+ }
117
+ const hoursMinutesValidator = {
118
+ name: "hoursMinutes",
119
+ validation(value, _element, config) {
120
+ return isEmpty(value) || isSet(HoursMinutesValidatorUtils.getParserFromConfig(config)(value));
121
+ }
122
+ };
123
+ const greaterThanTimeValidator = {
124
+ name: "greaterThanTime",
125
+ validation(value, _element, config) {
126
+ return HoursMinutesValidatorUtils.validate(value, config, "limit", (value2, limit) => {
127
+ return value2 > limit;
128
+ });
129
+ }
130
+ };
131
+ const lessThanTimeValidator = {
132
+ name: "lessThanTime",
133
+ validation(value, _element, config) {
134
+ return HoursMinutesValidatorUtils.validate(value, config, "limit", (value2, limit) => {
135
+ return value2 < limit;
136
+ });
137
+ }
138
+ };
139
+ const maxTimeValidator = {
140
+ name: "maxTime",
141
+ validation(value, _element, config) {
142
+ return HoursMinutesValidatorUtils.validate(value, config, this.name, (value2, limit) => {
143
+ return value2 <= limit;
144
+ });
145
+ }
146
+ };
147
+ const minTimeValidator = {
148
+ name: "minTime",
149
+ validation(value, _element, config) {
150
+ return HoursMinutesValidatorUtils.validate(value, config, this.name, (value2, limit) => {
151
+ return value2 >= limit;
152
+ });
153
+ }
154
+ };
155
+ const validators = [hoursMinutesValidator, greaterThanTimeValidator, lessThanTimeValidator, maxTimeValidator, minTimeValidator];
156
+ for (const validator of validators) {
157
+ ValidationService.registerValidator(validator);
158
+ }
159
+ const _sfc_main$1 = defineComponent({
160
+ name: "XTimeTextField",
161
+ extends: FTextField,
162
+ mixins: [TranslationMixin],
163
+ props: {
164
+ formatter: {
165
+ type: Function,
166
+ required: false,
167
+ default: formatNumberToTime
168
+ },
169
+ parser: {
170
+ type: Function,
171
+ required: false,
172
+ default: parseTimeToNumber
173
+ }
174
+ },
175
+ setup() {
176
+ return {
177
+ textFieldTableMode: inject("textFieldTableMode", false)
178
+ };
179
+ },
180
+ mounted() {
181
+ const inputElement = this.$el.querySelector("input");
182
+ if (!isSet(inputElement)) {
183
+ throw new Error(`Could not find input element in XTimeTextField with id ${this.$el.id}`);
184
+ }
185
+ ValidationService.addValidatorsToElement(inputElement, {
186
+ maxLength: {
187
+ length: 10
188
+ },
189
+ hoursMinutes: {}
190
+ }, true);
191
+ inputElement.setAttribute("inputmode", "numeric");
192
+ ValidationService.validateElement(inputElement);
193
+ }
194
+ });
195
+ const _sfc_main = defineComponent({
196
+ name: "XSearchBar",
197
+ components: {
198
+ FIcon,
199
+ FSearchTextField
200
+ },
201
+ props: {
202
+ modelValue: {
203
+ type: String,
204
+ required: true
205
+ },
206
+ maxLength: {
207
+ type: Number,
208
+ default: 20
209
+ }
210
+ },
211
+ emits: ["update:modelValue", "changedValue"],
212
+ computed: {
213
+ value: {
214
+ get() {
215
+ return this.modelValue;
216
+ },
217
+ set(value) {
218
+ if (this.value !== value) {
219
+ this.$emit("changedValue", [this.value, value]);
220
+ }
221
+ this.$emit("update:modelValue", value);
222
+ }
223
+ }
224
+ }
225
+ });
226
+ const _export_sfc = (sfc, props) => {
227
+ const target = sfc.__vccOpts || sfc;
228
+ for (const [key, val] of props) {
229
+ target[key] = val;
230
+ }
231
+ return target;
232
+ };
233
+ const _hoisted_1 = {
234
+ class: "button button--primary search-bar-button",
235
+ type: "submit",
236
+ "data-test": "search-bar-submit"
237
+ };
238
+ function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
239
+ const _component_f_icon = resolveComponent("f-icon");
240
+ const _component_f_search_text_field = resolveComponent("f-search-text-field");
241
+ return openBlock(), createBlock(_component_f_search_text_field, {
242
+ modelValue: _ctx.value,
243
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => _ctx.value = $event),
244
+ class: "x-search-bar",
245
+ maxlength: _ctx.maxLength
246
+ }, {
247
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
248
+ tooltip: withCtx(() => [renderSlot(_ctx.$slots, "tooltip")]),
249
+ "input-right": withCtx(() => [createElementVNode("button", _hoisted_1, [createVNode(_component_f_icon, {
250
+ name: "search",
251
+ library: "f"
252
+ }), createTextVNode(), createElementVNode("span", null, [renderSlot(_ctx.$slots, "button-text", {}, () => [createTextVNode(" Sök ")])])])]),
253
+ _: 3
254
+ /* FORWARDED */
255
+ }, 8, ["modelValue", "maxlength"]);
256
+ }
257
+ const XSearchBar = /* @__PURE__ */_export_sfc(_sfc_main, [["render", _sfc_render]]);
258
+ export { HOURS_MINUTES_REGEXP, HOURS_MINUTES_WITHOUT_COLON_REGEXP, HoursMinutesValidatorUtils, XSearchBar, _sfc_main$1 as XTimeTextField, forgivingParseTimeToNumber, formatNumberToTime, hoursMinutesStringToMinutes, minutesToHoursFloat, minutesToHoursMinutesString, minutesToObject, minutesToUserFriendlyString, parseTimeToNumber, splitHoursMinutes };