@ktjs/shared 0.23.17 → 0.23.20
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/dist/index.d.ts +162 -199
- package/dist/index.mjs +131 -115
- package/dist/index.mjs.map +1 -0
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,199 +1,162 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
*
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
*
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
*
|
|
113
|
-
*/
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
*
|
|
133
|
-
*/
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
| 'input'
|
|
164
|
-
| 'link'
|
|
165
|
-
| 'meta'
|
|
166
|
-
| 'meter'
|
|
167
|
-
| 'noembed'
|
|
168
|
-
| 'noframes'
|
|
169
|
-
| 'noscript'
|
|
170
|
-
| 'optgroup'
|
|
171
|
-
| 'param'
|
|
172
|
-
| 'progress'
|
|
173
|
-
| 'rp'
|
|
174
|
-
| 'select'
|
|
175
|
-
| 'style'
|
|
176
|
-
| 'template'
|
|
177
|
-
| 'textarea'
|
|
178
|
-
| 'title'
|
|
179
|
-
| 'video'
|
|
180
|
-
| 'wbr'
|
|
181
|
-
| 'embed'
|
|
182
|
-
| 'frame'
|
|
183
|
-
| 'keygen'
|
|
184
|
-
| 'option';
|
|
185
|
-
|
|
186
|
-
declare const originAppend: (...nodes: (Node | string)[]) => void;
|
|
187
|
-
|
|
188
|
-
export declare type otherstring = string & {};
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Parse query string into object
|
|
192
|
-
*/
|
|
193
|
-
export declare const parseQuery: (queryString: string) => Record<string, string>;
|
|
194
|
-
|
|
195
|
-
export declare type SVGJSXTag = HTMLTag | ((props?: any) => SVGElement) | ((props?: any) => Promise<SVGElement>);
|
|
196
|
-
|
|
197
|
-
export declare type SVGTag = keyof SVGElementTagNameMap;
|
|
198
|
-
|
|
199
|
-
export { }
|
|
1
|
+
declare const $isArray: (arg: any) => arg is any[];
|
|
2
|
+
declare const $ArrayFrom: {
|
|
3
|
+
<T>(arrayLike: ArrayLike<T>): T[];
|
|
4
|
+
<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
|
|
5
|
+
<T>(iterable: Iterable<T> | ArrayLike<T>): T[];
|
|
6
|
+
<T, U>(iterable: Iterable<T> | ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
|
|
7
|
+
};
|
|
8
|
+
declare const $is: (value1: any, value2: any) => boolean;
|
|
9
|
+
declare const $assign: {
|
|
10
|
+
<T extends {}, U>(target: T, source: U): T & U;
|
|
11
|
+
<T extends {}, U, V>(target: T, source1: U, source2: V): T & U & V;
|
|
12
|
+
<T extends {}, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
|
|
13
|
+
(target: object, ...sources: any[]): any;
|
|
14
|
+
};
|
|
15
|
+
declare const $hasOwn: (v: PropertyKey) => boolean;
|
|
16
|
+
declare const $toString: () => string;
|
|
17
|
+
declare const $keys: <T>(o: T) => Array<keyof T>;
|
|
18
|
+
declare const $defines: <T>(o: T, properties: PropertyDescriptorMap & ThisType<any>) => T;
|
|
19
|
+
declare const $define: <T>(o: T, p: PropertyKey, attributes: PropertyDescriptor & ThisType<any>) => T;
|
|
20
|
+
declare const $entries: <T>(o: T) => Array<[keyof T, T[keyof T]]>;
|
|
21
|
+
declare const $random: () => number;
|
|
22
|
+
declare const $isThenable: (o: any) => o is Promise<any>;
|
|
23
|
+
|
|
24
|
+
type otherstring = string & {};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Normal HTML tags like `div`, `span`, `a`, etc.
|
|
28
|
+
*/
|
|
29
|
+
type HTMLTag = keyof HTMLElementTagNameMap;
|
|
30
|
+
type SVGTag = keyof SVGElementTagNameMap;
|
|
31
|
+
type MathMLTag = keyof MathMLElementTagNameMap;
|
|
32
|
+
|
|
33
|
+
type HTMLJSXTag = HTMLTag | ((props?: any) => HTMLElement) | ((props?: any) => Promise<HTMLElement>);
|
|
34
|
+
type SVGJSXTag = HTMLTag | ((props?: any) => SVGElement) | ((props?: any) => Promise<SVGElement>);
|
|
35
|
+
type MathMLJSXTag = HTMLTag | ((props?: any) => MathMLElement) | ((props?: any) => Promise<MathMLElement>);
|
|
36
|
+
type JSXTag = HTMLJSXTag | SVGJSXTag | MathMLJSXTag;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the tags that makes HTMLElementTagNameMap[tag] = HTMLElement
|
|
40
|
+
*/
|
|
41
|
+
type NonSpecialTags = {
|
|
42
|
+
[K in keyof HTMLElementTagNameMap]: HTMLElement extends HTMLElementTagNameMap[K] ? K : never;
|
|
43
|
+
}[keyof HTMLElementTagNameMap];
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* This is tested on 15 browsers (most popular ones)
|
|
47
|
+
* - appending a text node to these tags takes no effect.
|
|
48
|
+
* - No effect means `innerText` does not include the text in the text node.
|
|
49
|
+
* @see {@link src/core/h/no-text-node.ts}
|
|
50
|
+
*/
|
|
51
|
+
type NoTextNodeTag =
|
|
52
|
+
| 'area'
|
|
53
|
+
| 'audio'
|
|
54
|
+
| 'base'
|
|
55
|
+
| 'basefont'
|
|
56
|
+
| 'br'
|
|
57
|
+
| 'canvas'
|
|
58
|
+
| 'datalist'
|
|
59
|
+
| 'details'
|
|
60
|
+
| 'dialog'
|
|
61
|
+
| 'frameset'
|
|
62
|
+
| 'head'
|
|
63
|
+
| 'iframe'
|
|
64
|
+
| 'img'
|
|
65
|
+
| 'input'
|
|
66
|
+
| 'link'
|
|
67
|
+
| 'meta'
|
|
68
|
+
| 'meter'
|
|
69
|
+
| 'noembed'
|
|
70
|
+
| 'noframes'
|
|
71
|
+
| 'noscript'
|
|
72
|
+
| 'optgroup'
|
|
73
|
+
| 'param'
|
|
74
|
+
| 'progress'
|
|
75
|
+
| 'rp'
|
|
76
|
+
| 'select'
|
|
77
|
+
| 'style'
|
|
78
|
+
| 'template'
|
|
79
|
+
| 'textarea'
|
|
80
|
+
| 'title'
|
|
81
|
+
| 'video'
|
|
82
|
+
| 'wbr'
|
|
83
|
+
| 'embed'
|
|
84
|
+
| 'frame'
|
|
85
|
+
| 'keygen'
|
|
86
|
+
| 'option';
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* These fields of HTMLElement can trigger `change`.
|
|
90
|
+
*/
|
|
91
|
+
type ChangeTriggerField = 'value' | 'checked' | 'selected' | 'valueAsDate' | 'valueAsNumber';
|
|
92
|
+
|
|
93
|
+
type InputElementTag = 'input' | 'select' | 'textarea';
|
|
94
|
+
|
|
95
|
+
declare const $isNode: (x: any) => x is ChildNode;
|
|
96
|
+
/**
|
|
97
|
+
* Safe replace `oldNode` With `newNode`
|
|
98
|
+
* - This function is not used everywhere. Because there is no need to check every time.
|
|
99
|
+
*/
|
|
100
|
+
declare const $replaceNode: (oldNode: unknown, newNode: unknown) => void;
|
|
101
|
+
declare const $parseStyle: (style: unknown) => string;
|
|
102
|
+
type ChangeHandler<T = string> = (value: T, ...args: any[]) => void;
|
|
103
|
+
/**
|
|
104
|
+
* Used for `k-model`
|
|
105
|
+
*/
|
|
106
|
+
declare const $applyModel: (element: HTMLElementTagNameMap[InputElementTag], valueRef: {
|
|
107
|
+
value: unknown;
|
|
108
|
+
addOnChange: (fn: (newValue: unknown) => void) => void;
|
|
109
|
+
}, propName: "value" | "checked", eventName: "change" | "input") => void;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Default empty function
|
|
113
|
+
*/
|
|
114
|
+
declare const $emptyFn: (...args: any[]) => any;
|
|
115
|
+
declare const $emptyArray: any[];
|
|
116
|
+
declare const $emptyObject: any;
|
|
117
|
+
declare const $identity: (x: any) => any;
|
|
118
|
+
/**
|
|
119
|
+
* SameValueZero comparison, similar to `Object.is` but treats `+0 === -0`
|
|
120
|
+
*/
|
|
121
|
+
declare const $SameValueZero: (x: unknown, y: unknown) => boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Safe and quick forEach implementation that works with array-like objects and handles sparse arrays.
|
|
124
|
+
*/
|
|
125
|
+
declare const $forEach: (array: unknown[], callback: (item: unknown, index: number, array: unknown[]) => void) => void;
|
|
126
|
+
/**
|
|
127
|
+
* Async version of $forEach that allows for asynchronous callbacks. It processes items sequentially, awaiting each callback before moving to the next.
|
|
128
|
+
*/
|
|
129
|
+
declare const $forEachAsync: (array: unknown[], callback: (item: unknown, index: number, array: unknown[]) => void) => Promise<void>;
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Normalize path by joining parts and ensuring leading slash
|
|
133
|
+
*/
|
|
134
|
+
declare const normalizePath: (...paths: string[]) => string;
|
|
135
|
+
/**
|
|
136
|
+
* Parse query string into object
|
|
137
|
+
*/
|
|
138
|
+
declare const parseQuery: (queryString: string) => Record<string, string>;
|
|
139
|
+
/**
|
|
140
|
+
* Build query string from object
|
|
141
|
+
*/
|
|
142
|
+
declare const buildQuery: (query: Record<string, string>) => string;
|
|
143
|
+
/**
|
|
144
|
+
* Substitute params into path pattern
|
|
145
|
+
* @example '/user/:id' + {id: '123'} => '/user/123'
|
|
146
|
+
*/
|
|
147
|
+
declare const emplaceParams: (path: string, params: Record<string, string>) => string;
|
|
148
|
+
/**
|
|
149
|
+
* Extract dynamic params from path using pattern
|
|
150
|
+
* @example pattern: '/user/:id', path: '/user/123' => {id: '123'}
|
|
151
|
+
*/
|
|
152
|
+
declare const extractParams: (pattern: string, path: string) => Record<string, string> | null;
|
|
153
|
+
|
|
154
|
+
interface KTReactiveLike<T = unknown> {
|
|
155
|
+
isKT: true;
|
|
156
|
+
value: T;
|
|
157
|
+
addOnChange(fn: (newValue: T, oldValue: T) => void): void;
|
|
158
|
+
removeOnChange?(fn: (newValue: T, oldValue: T) => void): boolean;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export { $ArrayFrom, $SameValueZero, $applyModel, $assign, $define, $defines, $emptyArray, $emptyFn, $emptyObject, $entries, $forEach, $forEachAsync, $hasOwn, $identity, $is, $isArray, $isNode, $isThenable, $keys, $parseStyle, $random, $replaceNode, $toString, buildQuery, emplaceParams, extractParams, normalizePath, parseQuery };
|
|
162
|
+
export type { ChangeHandler, ChangeTriggerField, HTMLJSXTag, HTMLTag, InputElementTag, JSXTag, KTReactiveLike, MathMLJSXTag, MathMLTag, NoTextNodeTag, NonSpecialTags, SVGJSXTag, SVGTag, otherstring };
|
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// Cached native methods for performance optimization
|
|
1
2
|
const $isArray = Array.isArray;
|
|
2
3
|
const $ArrayFrom = Array.from;
|
|
3
4
|
const $is = Object.is;
|
|
@@ -9,152 +10,167 @@ const $defines = Object.defineProperties;
|
|
|
9
10
|
const $define = Object.defineProperty;
|
|
10
11
|
const $entries = Object.entries;
|
|
11
12
|
const $random = Math.random;
|
|
12
|
-
const $isThenable = (o) => typeof o?.then ===
|
|
13
|
+
const $isThenable = (o) => typeof o?.then === 'function';
|
|
13
14
|
|
|
14
|
-
if (typeof Symbol ===
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
if (typeof Symbol === 'undefined') {
|
|
16
|
+
window.Symbol = function Symbol(description) {
|
|
17
|
+
return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;
|
|
18
|
+
};
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
// DOM manipulation utilities
|
|
22
|
+
// # dom natives
|
|
20
23
|
const $isNode = (x) => x?.nodeType > 0;
|
|
24
|
+
/**
|
|
25
|
+
* Safe replace `oldNode` With `newNode`
|
|
26
|
+
* - This function is not used everywhere. Because there is no need to check every time.
|
|
27
|
+
*/
|
|
21
28
|
const $replaceNode = (oldNode, newNode) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
oldNode.replaceWith(newNode);
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
const $appendChild = HTMLElement.prototype.appendChild;
|
|
30
|
-
const originAppend = HTMLElement.prototype.append;
|
|
31
|
-
const $append = (
|
|
32
|
-
// for ie 9/10/11
|
|
33
|
-
typeof originAppend === "function" ? originAppend : function(...nodes) {
|
|
34
|
-
if (nodes.length < 50) {
|
|
35
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
36
|
-
const node = nodes[i];
|
|
37
|
-
if (typeof node === "string") {
|
|
38
|
-
$appendChild.call(this, document.createTextNode(node));
|
|
39
|
-
} else {
|
|
40
|
-
$appendChild.call(this, node);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
const fragment = document.createDocumentFragment();
|
|
45
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
46
|
-
const node = nodes[i];
|
|
47
|
-
if (typeof node === "string") {
|
|
48
|
-
$appendChild.call(fragment, document.createTextNode(node));
|
|
49
|
-
} else {
|
|
50
|
-
$appendChild.call(fragment, node);
|
|
29
|
+
if ($isNode(oldNode) && $isNode(newNode)) {
|
|
30
|
+
if (newNode.contains(oldNode)) {
|
|
31
|
+
newNode.remove();
|
|
51
32
|
}
|
|
52
|
-
|
|
53
|
-
$appendChild.call(this, fragment);
|
|
33
|
+
oldNode.replaceWith(newNode);
|
|
54
34
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
HTMLButtonElement.prototype,
|
|
59
|
-
"disabled"
|
|
60
|
-
);
|
|
35
|
+
};
|
|
36
|
+
// # DOM utilities
|
|
37
|
+
// Same as it is in @ktjs/core
|
|
61
38
|
const $parseStyle = (style) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
if (style && typeof style === "object") {
|
|
69
|
-
if (style.isKT) {
|
|
70
|
-
return $parseStyle(style.value);
|
|
39
|
+
if (!style) {
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
if (typeof style === 'string') {
|
|
43
|
+
return style;
|
|
71
44
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
45
|
+
// already !style === false
|
|
46
|
+
if (typeof style === 'object') {
|
|
47
|
+
if (style.isKT) {
|
|
48
|
+
return $parseStyle(style.value);
|
|
49
|
+
}
|
|
50
|
+
return $entries(style)
|
|
51
|
+
.map((entry) => {
|
|
52
|
+
const cssKey = entry[0].replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
53
|
+
return `${cssKey}:${entry[1]}`;
|
|
54
|
+
})
|
|
55
|
+
.join(';');
|
|
56
|
+
}
|
|
57
|
+
return '';
|
|
78
58
|
};
|
|
59
|
+
/**
|
|
60
|
+
* Used for `k-model`
|
|
61
|
+
*/
|
|
79
62
|
const $applyModel = (element, valueRef, propName, eventName) => {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
63
|
+
element[propName] = valueRef.value; // initialize
|
|
64
|
+
valueRef.addOnChange((newValue) => (element[propName] = newValue));
|
|
65
|
+
element.addEventListener(eventName, () => (valueRef.value = element[propName]));
|
|
83
66
|
};
|
|
84
67
|
|
|
68
|
+
// String manipulation utilities
|
|
69
|
+
/**
|
|
70
|
+
* Default empty function
|
|
71
|
+
*/
|
|
85
72
|
const $emptyFn = (() => true);
|
|
86
73
|
const $emptyArray = [];
|
|
87
|
-
const $emptyObject =
|
|
88
|
-
const $
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
74
|
+
const $emptyObject = Object.create(null);
|
|
75
|
+
const $identity = (x) => x;
|
|
76
|
+
/**
|
|
77
|
+
* SameValueZero comparison, similar to `Object.is` but treats `+0 === -0`
|
|
78
|
+
*/
|
|
79
|
+
const $SameValueZero = (x, y) => (x !== x && y !== y) || x === y;
|
|
80
|
+
/**
|
|
81
|
+
* Safe and quick forEach implementation that works with array-like objects and handles sparse arrays.
|
|
82
|
+
*/
|
|
94
83
|
const $forEach = (array, callback) => {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
84
|
+
const len = array.length;
|
|
85
|
+
for (let i = 0; i < len; i++) {
|
|
86
|
+
callback(array[i], i, array);
|
|
87
|
+
}
|
|
99
88
|
};
|
|
89
|
+
/**
|
|
90
|
+
* Async version of $forEach that allows for asynchronous callbacks. It processes items sequentially, awaiting each callback before moving to the next.
|
|
91
|
+
*/
|
|
100
92
|
const $forEachAsync = async (array, callback) => {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
93
|
+
const len = array.length;
|
|
94
|
+
for (let i = 0; i < len; i++) {
|
|
95
|
+
await callback(array[i], i, array);
|
|
96
|
+
}
|
|
105
97
|
};
|
|
106
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Normalize path by joining parts and ensuring leading slash
|
|
101
|
+
*/
|
|
107
102
|
const normalizePath = (...paths) => {
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
const p = paths
|
|
104
|
+
.map((p) => p.split('/'))
|
|
105
|
+
.flat()
|
|
106
|
+
.filter(Boolean);
|
|
107
|
+
return '/' + p.join('/');
|
|
110
108
|
};
|
|
109
|
+
/**
|
|
110
|
+
* Parse query string into object
|
|
111
|
+
*/
|
|
111
112
|
const parseQuery = (queryString) => {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
const params = queryString.replace(/^\?/, "").split("&");
|
|
117
|
-
for (const param of params) {
|
|
118
|
-
const [key, value] = param.split("=");
|
|
119
|
-
if (key) {
|
|
120
|
-
query[decodeURIComponent(key)] = value ? decodeURIComponent(value) : "";
|
|
113
|
+
const query = {};
|
|
114
|
+
if (!queryString || queryString === '?') {
|
|
115
|
+
return query;
|
|
121
116
|
}
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
const params = queryString.replace(/^\?/, '').split('&');
|
|
118
|
+
for (const param of params) {
|
|
119
|
+
const [key, value] = param.split('=');
|
|
120
|
+
if (key) {
|
|
121
|
+
query[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return query;
|
|
124
125
|
};
|
|
126
|
+
/**
|
|
127
|
+
* Build query string from object
|
|
128
|
+
*/
|
|
125
129
|
const buildQuery = (query) => {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
const keys = Object.keys(query);
|
|
131
|
+
if (keys.length === 0)
|
|
132
|
+
return '';
|
|
133
|
+
const params = keys.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`).join('&');
|
|
134
|
+
return `?${params}`;
|
|
130
135
|
};
|
|
136
|
+
/**
|
|
137
|
+
* Substitute params into path pattern
|
|
138
|
+
* @example '/user/:id' + {id: '123'} => '/user/123'
|
|
139
|
+
*/
|
|
131
140
|
const emplaceParams = (path, params) => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
141
|
+
let result = path;
|
|
142
|
+
for (const key in params) {
|
|
143
|
+
result = result.replace(`:${key}`, params[key]);
|
|
144
|
+
}
|
|
145
|
+
return result;
|
|
137
146
|
};
|
|
147
|
+
/**
|
|
148
|
+
* Extract dynamic params from path using pattern
|
|
149
|
+
* @example pattern: '/user/:id', path: '/user/123' => {id: '123'}
|
|
150
|
+
*/
|
|
138
151
|
const extractParams = (pattern, path) => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
152
|
+
const params = {};
|
|
153
|
+
const patternParts = pattern.split('/');
|
|
154
|
+
const pathParts = path.split('/');
|
|
155
|
+
if (patternParts.length !== pathParts.length) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
for (let i = 0; i < patternParts.length; i++) {
|
|
159
|
+
const patternPart = patternParts[i];
|
|
160
|
+
const pathPart = pathParts[i];
|
|
161
|
+
if (patternPart.startsWith(':')) {
|
|
162
|
+
const paramName = patternPart.slice(1);
|
|
163
|
+
params[paramName] = pathPart;
|
|
164
|
+
}
|
|
165
|
+
else if (patternPart !== pathPart) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
153
168
|
}
|
|
154
|
-
|
|
155
|
-
return params;
|
|
169
|
+
return params;
|
|
156
170
|
};
|
|
157
171
|
|
|
158
|
-
|
|
172
|
+
// incase that symbol is not supported
|
|
173
|
+
Object.defineProperty(window, '__ktjs__', { value: '0.23.20' });
|
|
159
174
|
|
|
160
|
-
export { $ArrayFrom, $
|
|
175
|
+
export { $ArrayFrom, $SameValueZero, $applyModel, $assign, $define, $defines, $emptyArray, $emptyFn, $emptyObject, $entries, $forEach, $forEachAsync, $hasOwn, $identity, $is, $isArray, $isNode, $isThenable, $keys, $parseStyle, $random, $replaceNode, $toString, buildQuery, emplaceParams, extractParams, normalizePath, parseQuery };
|
|
176
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../src/utils/native.ts","../src/misc/symbol-polyfill.ts","../src/utils/dom.ts","../src/utils/misc.ts","../src/utils/url.ts","../src/index.ts"],"sourcesContent":["// Cached native methods for performance optimization\n\nexport const $isArray = Array.isArray;\nexport const $ArrayFrom = Array.from;\n\nexport const $is = Object.is;\nexport const $assign = Object.assign;\nexport const $hasOwn = Object.prototype.hasOwnProperty;\nexport const $toString = Object.prototype.toString;\n\nexport const $keys = Object.keys as <T>(o: T) => Array<keyof T>;\nexport const $defines = Object.defineProperties;\nexport const $define = Object.defineProperty;\nexport const $entries = Object.entries as <T>(o: T) => Array<[keyof T, T[keyof T]]>;\n\nexport const $random = Math.random;\n\nexport const $isThenable = (o: any): o is Promise<any> => typeof o?.then === 'function';\n","import { $random } from '../utils/native.js';\n\nexport {};\nif (typeof Symbol === 'undefined') {\n (window as any).Symbol = function Symbol(description?: string) {\n return `@@SYMBOL_${description || ''}_${$random().toString(36).slice(2)}`;\n };\n}\n","// DOM manipulation utilities\n\nimport type { KTReactiveLike } from '../types/misc.js';\nimport type { InputElementTag } from '../types/global.js';\nimport { $entries } from './native.js';\n\n// # dom natives\n\nexport const $isNode = (x: any): x is ChildNode => x?.nodeType > 0;\n\n/**\n * Safe replace `oldNode` With `newNode`\n * - This function is not used everywhere. Because there is no need to check every time.\n */\nexport const $replaceNode = (oldNode: unknown, newNode: unknown) => {\n if ($isNode(oldNode) && $isNode(newNode)) {\n if (newNode.contains(oldNode)) {\n newNode.remove();\n }\n oldNode.replaceWith(newNode);\n }\n};\n\n// # DOM utilities\n\n// Same as it is in @ktjs/core\nexport const $parseStyle = (style: unknown): string => {\n if (!style) {\n return '';\n }\n if (typeof style === 'string') {\n return style;\n }\n\n // already !style === false\n if (typeof style === 'object') {\n if ((style as KTReactiveLike).isKT) {\n return $parseStyle((style as KTReactiveLike).value);\n }\n\n return $entries(style)\n .map((entry: [string, string]) => {\n const cssKey = entry[0].replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);\n return `${cssKey}:${entry[1]}`;\n })\n .join(';');\n }\n return '';\n};\n\nexport type ChangeHandler<T = string> = (value: T, ...args: any[]) => void;\n\n/**\n * Used for `k-model`\n */\nexport const $applyModel = (\n element: HTMLElementTagNameMap[InputElementTag],\n valueRef: { value: unknown; addOnChange: (fn: (newValue: unknown) => void) => void },\n propName: 'value' | 'checked',\n eventName: 'change' | 'input',\n) => {\n (element as any)[propName] = valueRef.value; // initialize\n valueRef.addOnChange((newValue) => ((element as any)[propName] = newValue));\n element.addEventListener(eventName, () => (valueRef.value = (element as any)[propName]));\n};\n","// String manipulation utilities\n\nimport { $is, $isArray } from './native.js';\n\n/**\n * Default empty function\n */\nexport const $emptyFn = (() => true) as (...args: any[]) => any;\nexport const $emptyArray: any[] = [];\nexport const $emptyObject = Object.create(null);\nexport const $identity = (x: any) => x;\n\n/**\n * SameValueZero comparison, similar to `Object.is` but treats `+0 === -0`\n */\nexport const $SameValueZero = (x: unknown, y: unknown): boolean => (x !== x && y !== y) || x === y;\n\n/**\n * Safe and quick forEach implementation that works with array-like objects and handles sparse arrays.\n */\nexport const $forEach = (\n array: unknown[],\n callback: (item: unknown, index: number, array: unknown[]) => void,\n): void => {\n const len = array.length;\n for (let i = 0; i < len; i++) {\n callback(array[i], i, array);\n }\n};\n\n/**\n * Async version of $forEach that allows for asynchronous callbacks. It processes items sequentially, awaiting each callback before moving to the next.\n */\nexport const $forEachAsync = async (\n array: unknown[],\n callback: (item: unknown, index: number, array: unknown[]) => void,\n): Promise<void> => {\n const len = array.length;\n for (let i = 0; i < len; i++) {\n await callback(array[i], i, array);\n }\n};\n","/**\n * Normalize path by joining parts and ensuring leading slash\n */\nexport const normalizePath = (...paths: string[]) => {\n const p = paths\n .map((p) => p.split('/'))\n .flat()\n .filter(Boolean);\n return '/' + p.join('/');\n};\n\n/**\n * Parse query string into object\n */\nexport const parseQuery = (queryString: string): Record<string, string> => {\n const query: Record<string, string> = {};\n if (!queryString || queryString === '?') {\n return query;\n }\n\n const params = queryString.replace(/^\\?/, '').split('&');\n for (const param of params) {\n const [key, value] = param.split('=');\n if (key) {\n query[decodeURIComponent(key)] = value ? decodeURIComponent(value) : '';\n }\n }\n return query;\n};\n\n/**\n * Build query string from object\n */\nexport const buildQuery = (query: Record<string, string>): string => {\n const keys = Object.keys(query);\n if (keys.length === 0) return '';\n\n const params = keys.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}`).join('&');\n return `?${params}`;\n};\n\n/**\n * Substitute params into path pattern\n * @example '/user/:id' + {id: '123'} => '/user/123'\n */\nexport const emplaceParams = (path: string, params: Record<string, string>): string => {\n let result = path;\n for (const key in params) {\n result = result.replace(`:${key}`, params[key]);\n }\n return result;\n};\n\n/**\n * Extract dynamic params from path using pattern\n * @example pattern: '/user/:id', path: '/user/123' => {id: '123'}\n */\nexport const extractParams = (pattern: string, path: string): Record<string, string> | null => {\n const params: Record<string, string> = {};\n const patternParts = pattern.split('/');\n const pathParts = path.split('/');\n\n if (patternParts.length !== pathParts.length) {\n return null;\n }\n\n for (let i = 0; i < patternParts.length; i++) {\n const patternPart = patternParts[i];\n const pathPart = pathParts[i];\n\n if (patternPart.startsWith(':')) {\n const paramName = patternPart.slice(1);\n params[paramName] = pathPart;\n } else if (patternPart !== pathPart) {\n return null;\n }\n }\n\n return params;\n};\n","// incase that symbol is not supported\nimport './misc/symbol-polyfill.js';\n\nexport * from './misc/comment.js';\nexport * from './utils/native.js';\nexport * from './utils/dom.js';\nexport * from './utils/misc.js';\nexport * from './utils/url.js';\n\nexport type * from './types/global.js';\nexport type * from './types/misc.js';\n\nObject.defineProperty(window, '__ktjs__', { value: '__VERSION__' });\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ktjs/shared",
|
|
3
|
-
"version": "0.23.
|
|
3
|
+
"version": "0.23.20",
|
|
4
4
|
"description": "Shared utilities and cached native methods for kt.js framework",
|
|
5
|
+
"description_zh": "kt.js 框架的共享工具与原生方法缓存。",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"module": "./dist/index.mjs",
|
|
7
8
|
"types": "./dist/index.d.ts",
|