@hkdigital/lib-sveltekit 0.0.42 → 0.0.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -40,7 +40,7 @@ All exports are in subfolders.
40
40
  For example to import a constant from `constants/regexp/index.js`
41
41
 
42
42
  ```svelte
43
- import { CHAR } from '@hkdigital/lib-sveltekit-test/constants/regexp';
43
+ import { CHAR } from '@hkdigital/lib-sveltekit/constants/regexp';
44
44
  ```
45
45
 
46
46
  ### Import CSS
@@ -51,7 +51,7 @@ For example:
51
51
 
52
52
  ```css
53
53
  /* src/app.css */
54
- @import '../node_modules/@hkdigital/lib-sveltekit-test/dist/css/utilities.postcss';
54
+ @import '../node_modules/@hkdigital/lib-sveltekit/dist/css/utilities.postcss';
55
55
  ```
56
56
 
57
57
  ### Enable tailwind processing
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @typedef {object} Options
3
+ * @property {boolean} walkArrays
4
+ * @property {boolean} ignoreEmptyObjectLeaves
5
+ * @property {boolean} expandPathKeys
6
+ * @property {boolean} outputIntermediateNodes
7
+ */
8
+ export default class IterableTree {
9
+ /**
10
+ * Construct an object that can be used to iterate paths and values in
11
+ * an object.
12
+ * - Returns path-value pairs for all leaves of the object (tree)
13
+ * - Iterates "own properties" only (not inherited properties)
14
+ *
15
+ * @param {object} obj - Object to iterate
16
+ * @param {Options} [options]
17
+ * @param {string[]} [_parentArrPath]
18
+ *
19
+ *
20
+ * @return {Iterator} iterable object
21
+ */
22
+ constructor(obj: object, options?: Options, _parentArrPath?: string[]);
23
+ obj: any;
24
+ _parentArrPath: string[];
25
+ /**
26
+ * Get an iterator to iterate over all object [ path, value ] entries
27
+ *
28
+ * @returns {Iterator} object entries iterator
29
+ */
30
+ entries(): Iterator<any, any, any>;
31
+ /**
32
+ * Get an iterator to iterate over all object paths
33
+ *
34
+ * @returns {Iterator} object path iterator
35
+ */
36
+ paths(): Iterator<any, any, any>;
37
+ /**
38
+ * Get an iterator to iterate over all values at the leaves of the paths in
39
+ * the object
40
+ *
41
+ * @returns {Iterator} object value iterator
42
+ */
43
+ values(): Iterator<any, any, any>;
44
+ #private;
45
+ }
46
+ export type Options = {
47
+ walkArrays: boolean;
48
+ ignoreEmptyObjectLeaves: boolean;
49
+ expandPathKeys: boolean;
50
+ outputIntermediateNodes: boolean;
51
+ };
@@ -0,0 +1,243 @@
1
+ /* ------------------------------------------------------------------ Imports */
2
+
3
+ import * as expect from '../../util/expect/index.js';
4
+
5
+ import { PATH_SEPARATOR } from '../../util/object/index.js';
6
+
7
+ /* ------------------------------------------------------------------ Typedef */
8
+
9
+ /**
10
+ * @typedef {object} Options
11
+ * @property {boolean} walkArrays
12
+ * @property {boolean} ignoreEmptyObjectLeaves
13
+ * @property {boolean} expandPathKeys
14
+ * @property {boolean} outputIntermediateNodes
15
+ */
16
+
17
+ /* ------------------------------------------------------------------ Exports */
18
+
19
+ export default class IterableTree {
20
+ /**
21
+ * @type {Options}
22
+ */
23
+ #options;
24
+
25
+ /**
26
+ * Construct an object that can be used to iterate paths and values in
27
+ * an object.
28
+ * - Returns path-value pairs for all leaves of the object (tree)
29
+ * - Iterates "own properties" only (not inherited properties)
30
+ *
31
+ * @param {object} obj - Object to iterate
32
+ * @param {Options} [options]
33
+ * @param {string[]} [_parentArrPath]
34
+ *
35
+ *
36
+ * @return {Iterator} iterable object
37
+ */
38
+ constructor(obj, options, _parentArrPath) {
39
+ //super( ...arguments );
40
+
41
+ expect.object(obj);
42
+
43
+ this.obj = obj;
44
+
45
+ this.#options = Object.assign(
46
+ {
47
+ walkArrays: false,
48
+ ignoreEmptyObjectLeaves: false,
49
+ expandPathKeys: false,
50
+ outputIntermediateNodes: false
51
+ },
52
+ options
53
+ );
54
+
55
+ this._parentArrPath = _parentArrPath || null;
56
+ }
57
+
58
+ /* --------------------------------------------------------- Public methods */
59
+
60
+ // -------------------------------------------------------------------- Method
61
+
62
+ /**
63
+ * Get an iterator to iterate over all object [ path, value ] entries
64
+ *
65
+ * @returns {Iterator} object entries iterator
66
+ */
67
+ *entries() {
68
+ const obj = this.obj;
69
+ const parentArrPath = this._parentArrPath;
70
+
71
+ const options = this.options;
72
+
73
+ let { expandPathKeys, ignoreEmptyObjectLeaves, outputIntermediateNodes } = this.#options;
74
+
75
+ if (parentArrPath) {
76
+ // Never expand keys if not in root object
77
+ expandPathKeys = false;
78
+ }
79
+
80
+ // @note keys are own properties only
81
+ const keys = Object.keys(obj);
82
+
83
+ let pathKeys;
84
+
85
+ if (expandPathKeys) {
86
+ pathKeys = [];
87
+ }
88
+
89
+ // -- STEP 1: Normal object iteration (and gather path keys)
90
+
91
+ for (let j = 0, n = keys.length; j < n; j = j + 1) {
92
+ const key = keys[j];
93
+
94
+ if (expandPathKeys && key.includes(PATH_SEPARATOR)) {
95
+ // Gather pathKeys
96
+ pathKeys.push(key);
97
+ continue;
98
+ }
99
+
100
+ const valueAtPath = obj[key];
101
+
102
+ if (undefined === valueAtPath) {
103
+ // Ignore path-value pair if valueAtPath is undefined
104
+ continue;
105
+ }
106
+
107
+ let path;
108
+
109
+ if (parentArrPath) {
110
+ path = parentArrPath.slice(0);
111
+ path.push(key);
112
+ } else {
113
+ path = [key];
114
+ }
115
+
116
+ // No recursion >>
117
+
118
+ if (!this.#shouldRecurse(valueAtPath)) {
119
+ if (
120
+ ignoreEmptyObjectLeaves &&
121
+ valueAtPath instanceof Object &&
122
+ 0 === Object.keys(valueAtPath).length
123
+ ) {
124
+ // Ignore empty object leave
125
+ continue;
126
+ }
127
+
128
+ yield [path, valueAtPath];
129
+ continue;
130
+ }
131
+
132
+ // Recursion >>
133
+
134
+ // console.log( { path, valueAtPath, outputIntermediateNodes } );
135
+
136
+ if (outputIntermediateNodes) {
137
+ // outputIntermediateNodes=true
138
+ // -> Output itermediate node
139
+
140
+ if (Array.isArray(valueAtPath)) {
141
+ // Intermediate node is an array
142
+ yield [path, []];
143
+ } else {
144
+ // Intermediate node is plain object
145
+ yield [path, {}];
146
+ }
147
+ }
148
+
149
+ const objectIterator = new IterableTree(valueAtPath, options, path);
150
+
151
+ for (const entry of objectIterator.entries()) {
152
+ yield entry;
153
+ }
154
+ } // end for
155
+
156
+ // -- STEP 2: Output entries from "path keys"
157
+
158
+ if (!pathKeys || !pathKeys.length) {
159
+ // No path keys -> done
160
+ return;
161
+ }
162
+
163
+ for (let j = 0, n = pathKeys.length; j < n; j = j + 1) {
164
+ // @note path keys do not output intermediate nodes
165
+
166
+ const key = pathKeys[j];
167
+
168
+ const valueAtPath = obj[key];
169
+ const path = key.split(PATH_SEPARATOR);
170
+
171
+ yield [path, valueAtPath];
172
+ }
173
+ }
174
+
175
+ // -------------------------------------------------------------------- Method
176
+
177
+ /**
178
+ * Get an iterator to iterate over all object paths
179
+ *
180
+ * @returns {Iterator} object path iterator
181
+ */
182
+ *paths() {
183
+ for (const entry of this.entries()) {
184
+ yield entry[0];
185
+ }
186
+ }
187
+
188
+ // -------------------------------------------------------------------- Method
189
+
190
+ /**
191
+ * Get an iterator to iterate over all values at the leaves of the paths in
192
+ * the object
193
+ *
194
+ * @returns {Iterator} object value iterator
195
+ */
196
+ *values() {
197
+ for (const entry of this.entries()) {
198
+ yield entry[1];
199
+ }
200
+ }
201
+
202
+ // -------------------------------------------------------------------- Method
203
+
204
+ /**
205
+ * Returns true if the iterator should recurse into the specified value
206
+ *
207
+ * @param {string} value
208
+ *
209
+ * @return {boolean} true if the value should be iterated
210
+ */
211
+ #shouldRecurse(value) {
212
+ if (!(value instanceof Object)) {
213
+ // not an object -> no recursion
214
+ return false;
215
+ }
216
+
217
+ const walkArrays = this.#options.walkArrays;
218
+
219
+ if (walkArrays && Array.isArray(value)) {
220
+ // walkArrays=true AND isArray
221
+
222
+ if (!value.length) {
223
+ // Array is empty -> no recursion
224
+ return false;
225
+ }
226
+
227
+ return true;
228
+ }
229
+
230
+ if ('[object Object]' !== value.toString()) {
231
+ // Not a plain object -> no recursion
232
+ return false;
233
+ }
234
+
235
+ if (Object.keys(value).length) {
236
+ // Object is not empty -> recursion
237
+ return true;
238
+ }
239
+
240
+ // Otherwise -> no recursion
241
+ return false;
242
+ }
243
+ } // end class
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Construct a Selector class
3
+ */
4
+ export default class Selector {
5
+ /**
6
+ * Constructor
7
+ *
8
+ * @param {object|null} selector
9
+ */
10
+ constructor(selector: object | null);
11
+ /**
12
+ * Returns the first item from the list of items that matches the selector
13
+ *
14
+ * @param {object[]|null} items
15
+ *
16
+ * @returns {object|null} item or null if not found
17
+ */
18
+ findFirst(items: object[] | null): object | null;
19
+ /**
20
+ * Returns all items from the list of items that match the selector
21
+ *
22
+ * @param {object[]|null} items
23
+ *
24
+ * @returns {object|null} item or null if not found
25
+ */
26
+ findAll(items: object[] | null): object | null;
27
+ #private;
28
+ }
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Selector.js
3
+ *
4
+ * @description
5
+ * This file contains a class that can be used to select items from lists of
6
+ * objects.
7
+ *
8
+ * @TODO
9
+ * Allow other selection criteria than exact key-value pair matches
10
+ *
11
+ * @example
12
+ *
13
+ * import Selector from "./Selector.js";
14
+ *
15
+ * const selector = new Selector( { age: 42 } );
16
+ *
17
+ * const items =
18
+ * [
19
+ * { name: "Maria", age: 41 },
20
+ * { name: "John", age: 42 },
21
+ * { name: "Max", age: 43 }
22
+ * ]
23
+ *
24
+ * const item = selector.findFirst( items );
25
+ *
26
+ * console.log( item );
27
+ */
28
+
29
+ /* ------------------------------------------------------------------ Imports */
30
+
31
+ import * as expect from '../../util/expect/index.js';
32
+
33
+ /* ------------------------------------------------------------------- Export */
34
+
35
+ /**
36
+ * Construct a Selector class
37
+ */
38
+ export default class Selector {
39
+ /** @type {function|null} test function */
40
+ #testFn = null;
41
+
42
+ /**
43
+ * Constructor
44
+ *
45
+ * @param {object|null} selector
46
+ */
47
+ constructor(selector) {
48
+ this.#updateTestFn(selector);
49
+ }
50
+
51
+ // -------------------------------------------------------------------- Method
52
+
53
+ /**
54
+ * Returns the first item from the list of items that matches the selector
55
+ *
56
+ * @param {object[]|null} items
57
+ *
58
+ * @returns {object|null} item or null if not found
59
+ */
60
+ findFirst(items) {
61
+ if (!items) {
62
+ return null;
63
+ }
64
+
65
+ for (const item of items) {
66
+ if (this.#testFn(item)) {
67
+ return item;
68
+ }
69
+ }
70
+
71
+ return null;
72
+ }
73
+
74
+ // -------------------------------------------------------------------- Method
75
+
76
+ /**
77
+ * Returns all items from the list of items that match the selector
78
+ *
79
+ * @param {object[]|null} items
80
+ *
81
+ * @returns {object|null} item or null if not found
82
+ */
83
+ findAll(items) {
84
+ const result = [];
85
+
86
+ if (!items) {
87
+ return result;
88
+ }
89
+
90
+ for (const item of items) {
91
+ if (this.#testFn(item)) {
92
+ result.push(item);
93
+ }
94
+ }
95
+
96
+ return result;
97
+ }
98
+
99
+ /* ------------------------------------------------------- Internal methods */
100
+
101
+ /**
102
+ * Update the internal selector function
103
+ */
104
+ #updateTestFn(selector) {
105
+ // > Case A: selector=null
106
+
107
+ if (null === selector) {
108
+ this.#testFn = this.#returnTrue;
109
+ return;
110
+ }
111
+
112
+ // > Validate selector
113
+
114
+ expect.objectOrNull(selector);
115
+
116
+ const keys = Object.keys(selector);
117
+ const n = keys.length;
118
+
119
+ // > Case B: selector has not properties
120
+
121
+ if (!n) {
122
+ this.#testFn = this.#returnTrue;
123
+ return;
124
+ }
125
+
126
+ // > Case C: selector with single key-value pair
127
+
128
+ if (1 === n) {
129
+ const key = keys[0];
130
+ const value = selector[key];
131
+
132
+ this.#testFn = this.#testKeyValue.bind(this, key, value);
133
+ }
134
+
135
+ // > Case D: selector with multiple key-value pairs
136
+
137
+ const selectorValues = [];
138
+
139
+ for (const key of keys) {
140
+ selectorValues.push(selector[key]);
141
+ }
142
+
143
+ this.#testFn = this.#testMultipleKeyValues.bind(this, keys, selectorValues);
144
+ }
145
+
146
+ // -------------------------------------------------------------------- Method
147
+
148
+ /**
149
+ * Always return true
150
+ * - This function is used if the test function should always return true
151
+ *
152
+ * @returns {boolean} true
153
+ */
154
+ #returnTrue() {
155
+ return true;
156
+ }
157
+
158
+ // -------------------------------------------------------------------- Method
159
+
160
+ /**
161
+ * Return true if the item matches the key-value pair
162
+ * - This function is used if the test function should test a
163
+ * single key-value pair
164
+ */
165
+ #testKeyValue(key, value, item) {
166
+ return value === item[key];
167
+ }
168
+
169
+ // -------------------------------------------------------------------- Method
170
+
171
+ /**
172
+ * Return true if the item matches all key-value pairs
173
+ * - This function is used if the test function should test multiple
174
+ * key-value pairs
175
+ */
176
+ #testMultipleKeyValues(keys, values, item) {
177
+ let isMatch = true;
178
+
179
+ for (let j = 0, n = keys.length; j < n; j = j + 1) {
180
+ if (values[j] !== item[keys[j]]) {
181
+ isMatch = false;
182
+ break;
183
+ }
184
+ } // end for
185
+
186
+ return isMatch;
187
+ }
188
+ } // end class
@@ -0,0 +1,2 @@
1
+ export { default as Selector } from "./Selector.js";
2
+ export { default as IterableTree } from "./IterableTree.js";
@@ -0,0 +1,2 @@
1
+ export { default as Selector } from './Selector.js';
2
+ export { default as IterableTree } from './IterableTree.js';
@@ -1,2 +1,3 @@
1
+ export * as data from "./data/index.js";
1
2
  export * as streams from "./streams/index.js";
2
3
  export * as stores from "./stores/index.js";
@@ -1,2 +1,3 @@
1
+ export * as data from './data/index.js';
1
2
  export * as streams from './streams/index.js';
2
3
  export * as stores from './stores/index.js';
@@ -0,0 +1,49 @@
1
+ <script>
2
+ /**
3
+ *
4
+ * @type {{
5
+ * legendTitle: string,
6
+ * error?: boolean,
7
+ * name?: string,
8
+ * type: string,
9
+ * placeholder: string,
10
+ * classes?: string,
11
+ * requiredBoolean: boolean,
12
+ * warningSymbol: string,
13
+ * fieldClasses?: string,
14
+ * legendClasses?: string
15
+ * }}
16
+ *
17
+ */
18
+ let
19
+ {
20
+ legendTitle,
21
+ type,
22
+ placeholder,
23
+ error,
24
+ name,
25
+ requiredBoolean,
26
+ warningSymbol,
27
+ classes,
28
+ fieldClasses,
29
+ legendClasses
30
+ } = $props();
31
+
32
+ </script>
33
+
34
+ <fieldset
35
+ data-hk-input-field
36
+ class="flex w-full items-center rounded {fieldClasses}"
37
+ >
38
+ <legend class="px-2 {legendClasses}" class:error>{legendTitle}</legend>
39
+ <input
40
+ class='w-full border-none bg-transparent {classes}'
41
+ {type}
42
+ {placeholder}
43
+ {name}
44
+ required={requiredBoolean}
45
+ />
46
+ {#if error}
47
+ <img src={warningSymbol} class="mb-2 mr-8" alt="Warning symbol" />
48
+ {/if}
49
+ </fieldset>
@@ -0,0 +1,13 @@
1
+ export default HkInputField;
2
+ declare const HkInputField: import("svelte").Component<{
3
+ legendTitle: string;
4
+ error?: boolean;
5
+ name?: string;
6
+ type: string;
7
+ placeholder: string;
8
+ classes?: string;
9
+ requiredBoolean: boolean;
10
+ warningSymbol: string;
11
+ fieldClasses?: string;
12
+ legendClasses?: string;
13
+ }, {}, "">;
@@ -0,0 +1 @@
1
+ export { default as HkInputField } from "./HkInputField.svelte";
@@ -0,0 +1 @@
1
+ export { default as HkInputField } from './HkInputField.svelte';
package/dist/index.js CHANGED
@@ -4,6 +4,6 @@
4
4
  // @see package.json > exports
5
5
  //
6
6
  // @example
7
- // import { TimeStampSource } from '@hkdigital/lib-sveltekit-test/classes';
7
+ // import { TimeStampSource } from '@hkdigital/lib-sveltekit/classes';
8
8
  //
9
9
  //