danholibraryjs 1.7.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +2 -2
- package/dist/Classes/Events/Event.js +1 -1
- package/dist/Classes/Events/EventCollection.js +1 -1
- package/dist/Classes/Events/EventEmitter.d.ts +28 -4
- package/dist/Classes/Events/EventEmitter.js +24 -0
- package/dist/Classes/Time/Date.d.ts +5 -5
- package/dist/Classes/Time/Time.d.ts +3 -3
- package/dist/Classes/Time/TimeProperties.d.ts +2 -2
- package/dist/Classes/Time/TimeSpan.d.ts +1 -1
- package/dist/Classes/index.d.ts +1 -0
- package/dist/Classes/index.js +1 -0
- package/dist/Classes/store.d.ts +79 -0
- package/dist/Classes/store.js +84 -0
- package/dist/Extensions/Array.d.ts +8 -1
- package/dist/Extensions/Array.js +47 -10
- package/dist/Extensions/Document.d.ts +27 -0
- package/dist/Extensions/Document.js +32 -0
- package/dist/Extensions/Function.d.ts +14 -0
- package/dist/Extensions/Function.js +10 -0
- package/dist/Extensions/Map.d.ts +17 -1
- package/dist/Extensions/Map.js +24 -13
- package/dist/Extensions/Object/index.d.ts +49 -0
- package/dist/Extensions/Object/index.js +38 -0
- package/dist/Extensions/Object/properties.d.ts +28 -0
- package/dist/Extensions/Object/properties.js +20 -0
- package/dist/Extensions/String.d.ts +11 -1
- package/dist/Extensions/String.js +15 -7
- package/dist/Extensions/index.d.ts +5 -17
- package/dist/Extensions/index.js +8 -49
- package/dist/Functions/GetCSSProperty.d.ts +1 -1
- package/dist/Functions/GetNestedProperty.d.ts +9 -0
- package/dist/Functions/GetNestedProperty.js +23 -0
- package/dist/Functions/index.d.ts +1 -0
- package/dist/Functions/index.js +1 -0
- package/dist/Interfaces/ElementOptions.d.ts +4 -4
- package/dist/Types/BetterTypes.d.ts +3 -3
- package/dist/Types/Date.d.ts +6 -6
- package/dist/Types/Events.d.ts +2 -2
- package/dist/Types/PropertiesWith.d.ts +2 -2
- package/dist/Types/TransformTypes.d.ts +2 -2
- package/dist/Types/index.d.ts +21 -6
- package/docs/Classes.md +33 -0
- package/docs/Extensions.md +7 -0
- package/docs/Functions.md +8 -0
- package/docs/Types.md +30 -17
- package/package.json +6 -3
- package/src/Classes/Events/Event.ts +1 -1
- package/src/Classes/Events/EventCollection.ts +1 -1
- package/src/Classes/Events/EventEmitter.ts +40 -5
- package/src/Classes/index.ts +2 -1
- package/src/Classes/store.ts +98 -0
- package/src/Extensions/Array.ts +49 -11
- package/src/Extensions/Document.ts +58 -0
- package/src/Extensions/Function.ts +18 -0
- package/src/Extensions/Map.ts +24 -9
- package/src/Extensions/Object/index.ts +82 -0
- package/src/Extensions/Object/properties.ts +51 -0
- package/src/Extensions/String.ts +17 -6
- package/src/Extensions/index.ts +7 -66
- package/src/Functions/GetNestedProperty.ts +29 -0
- package/src/Functions/index.ts +1 -0
- package/src/Interfaces/ElementOptions.ts +2 -2
- package/src/Types/index.ts +27 -2
- package/tsconfig.json +2 -2
- package/Time.xlsx +0 -0
- package/dist/Extensions/Object.d.ts +0 -16
- package/dist/Extensions/Object.js +0 -8
- package/src/Extensions/Object.ts +0 -25
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "danholibraryjs",
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
"version": "1.10.0",
|
|
4
5
|
"description": "Library for Javascript.",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
7
8
|
"scripts": {
|
|
8
9
|
"build": "npx tsc --project tsconfig.json",
|
|
9
|
-
"build-watch": "npx tsc --project tsconfig.json --watch true"
|
|
10
|
+
"build-watch": "npx tsc --project tsconfig.json --watch true",
|
|
11
|
+
"login-github": "npm login --scope=@DanielSimonsen90 --registry=https://npm.pkg.github.com",
|
|
12
|
+
"login-npm": "npm login --scope@danhosaur --registry=https://registry.npmjs.org"
|
|
10
13
|
},
|
|
11
14
|
"repository": {
|
|
12
15
|
"type": "git",
|
|
@@ -19,4 +22,4 @@
|
|
|
19
22
|
"url": "https://github.com/DanielSimonsen90/DanhoLibraryJS/issues"
|
|
20
23
|
},
|
|
21
24
|
"homepage": "https://github.com/DanielSimonsen90/DanhoLibraryJS#readme"
|
|
22
|
-
}
|
|
25
|
+
}
|
|
@@ -58,7 +58,7 @@ export class Event<
|
|
|
58
58
|
*/
|
|
59
59
|
public on(listener: EventHandler<Events, Name>, prepend = false) {
|
|
60
60
|
if (this.limit > 0 && this._listeners.length + 1 > this.limit) {
|
|
61
|
-
throw new Error(`Event limit, ${this.limit}, reached for event ${this.name}!`);
|
|
61
|
+
throw new Error(`Event limit, ${this.limit}, reached for event ${this.name.toString()}!`);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
if (prepend) this._listeners = [listener, ...this._listeners]
|
|
@@ -99,7 +99,7 @@ import Event from './Event';
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
const event = this.get(eventName);
|
|
102
|
-
if (!event) throw new Error(`Unknown event, ${eventName}!`);
|
|
102
|
+
if (!event) throw new Error(`Unknown event, ${eventName.toString()}!`);
|
|
103
103
|
|
|
104
104
|
event.limit = limit;
|
|
105
105
|
this._events.set(eventName, event as any);
|
|
@@ -6,6 +6,30 @@ import { BaseEvent, EventHandler } from '../../Types';
|
|
|
6
6
|
* @borrows EventCollection
|
|
7
7
|
* @borrows BaseEvent
|
|
8
8
|
* @borrows EventHandler
|
|
9
|
+
*
|
|
10
|
+
* @example ```ts
|
|
11
|
+
* import { EventEmitter } from 'danholibraryjs';
|
|
12
|
+
*
|
|
13
|
+
* type EventTypes = {
|
|
14
|
+
* create: [username: string, password: string],
|
|
15
|
+
* update: [id: string, user: User],
|
|
16
|
+
* delete: [id: string, reason?: string],
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* const emitter = new EventEmitter<EventTypes>(new Map([
|
|
20
|
+
* ['create', (username, password) => {
|
|
21
|
+
* return { username, password };
|
|
22
|
+
* }],
|
|
23
|
+
* ['update', (id, user) => {
|
|
24
|
+
* return { id, ...user };
|
|
25
|
+
* }]
|
|
26
|
+
* ]));
|
|
27
|
+
*
|
|
28
|
+
* const onDelete = (id: string, reason?: string) => console.log(`User ${id} was deleted because ${reason}`);
|
|
29
|
+
* emitter.on('delete', onDelete);
|
|
30
|
+
* emitter.emit('delete', '1', 'No longer needed');
|
|
31
|
+
* emitter.off('delete', onDelete);
|
|
32
|
+
* ```
|
|
9
33
|
*/
|
|
10
34
|
export class EventEmitter<Events extends BaseEvent<string, Array<any>>> {
|
|
11
35
|
/**@param events Map<name: string, handlers: EventHandler[]>*/
|
|
@@ -22,7 +46,10 @@ export class EventEmitter<Events extends BaseEvent<string, Array<any>>> {
|
|
|
22
46
|
* @param listener Callback function to run, when event occurs
|
|
23
47
|
* @returns this
|
|
24
48
|
*/
|
|
25
|
-
public on<Return extends any, Event extends keyof Events>(
|
|
49
|
+
public on<Return extends any, Event extends keyof Events>(
|
|
50
|
+
event: Event,
|
|
51
|
+
listener: EventHandler<Events, Event, Return>
|
|
52
|
+
): EventEmitter<Events> {
|
|
26
53
|
this._events.add(event, listener as any);
|
|
27
54
|
return this;
|
|
28
55
|
}
|
|
@@ -32,7 +59,10 @@ export class EventEmitter<Events extends BaseEvent<string, Array<any>>> {
|
|
|
32
59
|
* @param listener Callback function to run, when event occurs
|
|
33
60
|
* @returns this
|
|
34
61
|
*/
|
|
35
|
-
public once<Return extends any, Event extends keyof Events>(
|
|
62
|
+
public once<Return extends any, Event extends keyof Events>(
|
|
63
|
+
event: Event,
|
|
64
|
+
listener: EventHandler<Events, Event, Return>
|
|
65
|
+
): EventEmitter<Events> {
|
|
36
66
|
this._events.add(event, listener as any, true);
|
|
37
67
|
return this;
|
|
38
68
|
}
|
|
@@ -43,7 +73,10 @@ export class EventEmitter<Events extends BaseEvent<string, Array<any>>> {
|
|
|
43
73
|
* @param listener If left null, removes all listeners tied to event, else only removes listener from event
|
|
44
74
|
* @returns this
|
|
45
75
|
*/
|
|
46
|
-
public off<Return extends any, Event extends keyof Events>(
|
|
76
|
+
public off<Return extends any, Event extends keyof Events>(
|
|
77
|
+
event: Event | 'all' = "all",
|
|
78
|
+
listener?: EventHandler<Events, Event, Return>
|
|
79
|
+
): EventEmitter<Events> {
|
|
47
80
|
this._events.clear(event, listener);
|
|
48
81
|
return this;
|
|
49
82
|
}
|
|
@@ -55,7 +88,9 @@ export class EventEmitter<Events extends BaseEvent<string, Array<any>>> {
|
|
|
55
88
|
* @fires event
|
|
56
89
|
* @returns Array of listeners' reponses
|
|
57
90
|
*/
|
|
58
|
-
public emit<Return extends any, Event extends keyof Events>(
|
|
91
|
+
public emit<Return extends any, Event extends keyof Events>(
|
|
92
|
+
event: Event, ...args: Events[Event]
|
|
93
|
+
): Array<Return> {
|
|
59
94
|
return this._events.emit(event, ...args) as Array<Return>;
|
|
60
95
|
}
|
|
61
96
|
|
|
@@ -65,7 +100,7 @@ export class EventEmitter<Events extends BaseEvent<string, Array<any>>> {
|
|
|
65
100
|
* @param limit Limit of events to keep. If you want to limit amount of events saved, use 'all'.
|
|
66
101
|
* @returns this with the new limit
|
|
67
102
|
*/
|
|
68
|
-
public limit<Event extends keyof Events>(event: 'all' | Event, limit: number) {
|
|
103
|
+
public limit<Event extends keyof Events>(event: 'all' | Event, limit: number): EventEmitter<Events> {
|
|
69
104
|
this._events.limit<Event>(event, limit);
|
|
70
105
|
return this;
|
|
71
106
|
}
|
package/src/Classes/index.ts
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Arrayable, TransformType } from "../Types";
|
|
2
|
+
import { EventEmitter } from "./Events";
|
|
3
|
+
|
|
4
|
+
export type Reducer<State, Types extends Record<string, any[]>, Action extends keyof Types> = (state: State, ...args: Types[Action]) => State
|
|
5
|
+
export type Actions<State, ActionTypes extends Record<string, any[]>> = {
|
|
6
|
+
[Action in keyof ActionTypes]?: Arrayable<Reducer<State, ActionTypes, Action>>
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* EventEmitter, but it stores state and handles state change with reducers
|
|
11
|
+
*
|
|
12
|
+
* @Initialization Actions & initial state must be defined in type parameters. InitialState must be provided in constructor, whereas reducer is optional.
|
|
13
|
+
* The ActionType must have properties as strings and values as arrays.
|
|
14
|
+
*
|
|
15
|
+
* @HandlingActions Reducers can be added through constructor or using Store.on('action', reducer) or Store.once('action', reducer).
|
|
16
|
+
* Every state change must return the next state, apart from 'stateChange', which returns void/any
|
|
17
|
+
* Emit/Dispatch an action using Store.dispatch('action', ...args), ...args being the parameters from the ActionType.
|
|
18
|
+
* Store.emit should NOT be used, as it doesn't update the Store's state.
|
|
19
|
+
*
|
|
20
|
+
* Reducer functions can be removed using Store.off('action', reducer);
|
|
21
|
+
*
|
|
22
|
+
* @borrows EventEmitter
|
|
23
|
+
* @borrows Arrayable
|
|
24
|
+
*
|
|
25
|
+
* @example ```ts
|
|
26
|
+
* import { Store } from 'danholibraryjs';
|
|
27
|
+
*
|
|
28
|
+
* type Todo = {
|
|
29
|
+
* id: string,
|
|
30
|
+
* text: string,
|
|
31
|
+
* completed: boolean
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* type TodoActions = {
|
|
35
|
+
* create: [text: string],
|
|
36
|
+
* update: [id: string, text: string],
|
|
37
|
+
* toggleComplete: [id: string, force?: boolean],
|
|
38
|
+
* delete: [id: string],
|
|
39
|
+
* }
|
|
40
|
+
*
|
|
41
|
+
* const store = new Store<Array<Todo>, TodoActions>(new Array<Todo>(), new Map([
|
|
42
|
+
* create: (state, text) => {
|
|
43
|
+
* return [...state, {
|
|
44
|
+
* id: Math.random().toString(),
|
|
45
|
+
* text,
|
|
46
|
+
* completed: false
|
|
47
|
+
* }];
|
|
48
|
+
* },
|
|
49
|
+
* toggleComplete: (state, id, force) => {
|
|
50
|
+
* const todo = state.find(todo => todo.id === id);
|
|
51
|
+
* if (!todo) return state;
|
|
52
|
+
*
|
|
53
|
+
* return state.map(todo => (
|
|
54
|
+
* todo.id === id ? {
|
|
55
|
+
* ...todo,
|
|
56
|
+
* completed: force === undefined ? !todo.completed : force
|
|
57
|
+
* } : todo
|
|
58
|
+
* ));
|
|
59
|
+
* }
|
|
60
|
+
* ]));
|
|
61
|
+
*
|
|
62
|
+
* store.on('delete', (state, id) => {
|
|
63
|
+
* return state.filter(todo => todo.id !== id);
|
|
64
|
+
* });
|
|
65
|
+
*
|
|
66
|
+
* store.on('stateChange', (prevState, currentState) => console.log('State change', prevState, currentState));
|
|
67
|
+
*
|
|
68
|
+
* store.dispatch('create', 'Make store!');
|
|
69
|
+
*
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
export class Store<
|
|
73
|
+
State extends object,
|
|
74
|
+
ActionTypes extends Record<string, any[]>,
|
|
75
|
+
StoreActions extends Actions<State, ActionTypes> = Actions<State, ActionTypes>
|
|
76
|
+
> extends EventEmitter<
|
|
77
|
+
Record<keyof StoreActions, ActionTypes[keyof ActionTypes]>
|
|
78
|
+
& Record<'stateChange', [previous: State, current: State]>
|
|
79
|
+
> {
|
|
80
|
+
constructor(state: State, actions: StoreActions = {} as StoreActions) {
|
|
81
|
+
super(new Map(...Object.entries(actions).map(([action, reducers]) => [action, reducers as any])));
|
|
82
|
+
|
|
83
|
+
this._state = state;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private _state: State;
|
|
87
|
+
public get state(): State {
|
|
88
|
+
return this._state;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public dispatch<Action extends keyof ActionTypes>(action: Action, ...args: ActionTypes[Action]): State {
|
|
92
|
+
const previous = { ...this._state };
|
|
93
|
+
this._state = super.emit<State, Action>(action, ...args as any).reduce((state, returned) => ({ ...state, ...returned }), this.state);
|
|
94
|
+
|
|
95
|
+
super.emit<void, 'stateChange'>('stateChange', ...[previous, this.state] as any);
|
|
96
|
+
return this.state;
|
|
97
|
+
}
|
|
98
|
+
}
|
package/src/Extensions/Array.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
type UpdateFinder<T> = (item: T, index: number, self: Array<T>) => boolean
|
|
1
|
+
export type UpdateFinder<T> = (item: T, index: number, self: Array<T>) => boolean
|
|
4
2
|
|
|
5
3
|
declare global {
|
|
6
4
|
interface Array<T> {
|
|
@@ -28,30 +26,70 @@ declare global {
|
|
|
28
26
|
* Returns item matching index. If negative number, subtracts number from length
|
|
29
27
|
* @param i Index of item
|
|
30
28
|
*/
|
|
31
|
-
index(i: number): T
|
|
29
|
+
index(i: number): T,
|
|
30
|
+
/**
|
|
31
|
+
* For every x in array, execute callback
|
|
32
|
+
* @param every i.e every 2nd item in array
|
|
33
|
+
* @param callback Function to execute
|
|
34
|
+
* @returns Array of results
|
|
35
|
+
*/
|
|
36
|
+
nth<U>(every: number, callback: (item: T, index: number, collection: Array<T>, self: this) => U): Array<U>
|
|
32
37
|
}
|
|
33
38
|
}
|
|
34
39
|
|
|
35
|
-
|
|
40
|
+
function add<T>(this: Array<T>, ...items: Array<T>) {
|
|
36
41
|
this.push(...items);
|
|
37
42
|
return this;
|
|
38
43
|
}
|
|
39
|
-
Array.prototype.
|
|
40
|
-
|
|
44
|
+
Array.prototype.add = add;
|
|
45
|
+
|
|
46
|
+
function update<T>(this: Array<T>, old: T | number | UpdateFinder<T>, updated: T) {
|
|
47
|
+
const item = typeof old === 'number' ? this[old]
|
|
48
|
+
: typeof old === 'function' ? this.find(old as UpdateFinder<T>)
|
|
49
|
+
: old;
|
|
41
50
|
if (!item) throw new Error('Old was not found in array!');
|
|
42
51
|
|
|
43
52
|
const index = this.indexOf(item);
|
|
44
53
|
return this[index] = updated;
|
|
45
54
|
}
|
|
46
|
-
Array.prototype.
|
|
55
|
+
Array.prototype.update = update;
|
|
56
|
+
|
|
57
|
+
function remove<T>(this: Array<T>, value: T | number): Array<T> {
|
|
47
58
|
const index = typeof value === 'number' ? value : this.indexOf(value);
|
|
48
59
|
if (index > -1) this.splice(index, 1);
|
|
49
60
|
return this;
|
|
50
61
|
}
|
|
51
|
-
Array.prototype.
|
|
62
|
+
Array.prototype.remove = remove;
|
|
63
|
+
|
|
64
|
+
function random<T>(this: Array<T>): T {
|
|
52
65
|
const randomIndex = Math.round(Math.random() * this.length);
|
|
53
66
|
return this[randomIndex];
|
|
54
67
|
}
|
|
55
|
-
Array.prototype.
|
|
68
|
+
Array.prototype.random = random;
|
|
69
|
+
|
|
70
|
+
function index<T>(this: Array<T>, i: number): T {
|
|
56
71
|
return this[i < 0 ? this.length + i : i];
|
|
57
|
-
}
|
|
72
|
+
}
|
|
73
|
+
Array.prototype.index = index;
|
|
74
|
+
|
|
75
|
+
function nth<T, U>(this: Array<T>, every: number, callback: (item: T, index: number, collection: Array<T>, self: Array<T>) => U): Array<U> {
|
|
76
|
+
const result = new Array<U>();
|
|
77
|
+
let collection = new Array<T>();
|
|
78
|
+
|
|
79
|
+
for (let i = 0; i < this.length; i++) {
|
|
80
|
+
collection.push(this[i]);
|
|
81
|
+
|
|
82
|
+
if (i % every === 0) {
|
|
83
|
+
result.push(callback(this[i], i, collection, this));
|
|
84
|
+
collection = new Array<T>();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
Array.prototype.nth = nth;
|
|
91
|
+
|
|
92
|
+
export const ArrayExtensions = {
|
|
93
|
+
add, update, remove,
|
|
94
|
+
random, index, nth
|
|
95
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { IElement } from "../Types";
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface Document {
|
|
5
|
+
/**
|
|
6
|
+
* Creates an element like Document#createElement, however with construction options to assign values in construction instead of after construction.
|
|
7
|
+
* @param tagName HTMLElement tag name
|
|
8
|
+
* @param options Construction options, instead of assigning values after construction
|
|
9
|
+
* @param children Child elements
|
|
10
|
+
*/
|
|
11
|
+
createProperElement<Tag extends keyof HTMLElementTagNameMap>(tagName: Tag, options?: Partial<HTMLElementTagNameMap[Tag]>, ...children: Array<IElement>): HTMLElementTagNameMap[Tag]
|
|
12
|
+
createProperElement<Tag extends keyof HTMLElementTagNameMap>(tagName: Tag, ...children: Array<IElement>): HTMLElementTagNameMap[Tag]
|
|
13
|
+
createElementFromString<K extends keyof HTMLElementTagNameMap>(html: string, parentTag?: K): HTMLElementTagNameMap[K]
|
|
14
|
+
}
|
|
15
|
+
interface HTMLCollection {
|
|
16
|
+
/**
|
|
17
|
+
* Converts HTMLCollection to Element[]
|
|
18
|
+
*/
|
|
19
|
+
array(): Element[]
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function createElement<Tag extends keyof HTMLElementTagNameMap>(
|
|
24
|
+
this: Document, tagName: Tag,
|
|
25
|
+
options?: Partial<HTMLElementTagNameMap[Tag]> | string,
|
|
26
|
+
...children: Array<IElement>
|
|
27
|
+
): HTMLElementTagNameMap[Tag] {
|
|
28
|
+
|
|
29
|
+
const element = Object.assign(document.createElement(tagName), typeof options === 'string' ? {} : options);
|
|
30
|
+
children ??= typeof options === 'string' ? [options] as Array<IElement> : [];
|
|
31
|
+
typeof options === 'string' && children.unshift(options);
|
|
32
|
+
|
|
33
|
+
if (!children.length) return element;
|
|
34
|
+
else if (typeof children === 'string') element.innerHTML = children;
|
|
35
|
+
else if (children instanceof Array) children.forEach(child => (
|
|
36
|
+
typeof child === 'string' ?
|
|
37
|
+
element.innerHTML += child :
|
|
38
|
+
element.appendChild(child)
|
|
39
|
+
));
|
|
40
|
+
else element.appendChild(children);
|
|
41
|
+
return element;
|
|
42
|
+
|
|
43
|
+
}
|
|
44
|
+
Document.prototype.createProperElement = createElement;
|
|
45
|
+
|
|
46
|
+
function createElementFromString<Tag extends keyof HTMLElementTagNameMap>(this: Document, html: string, tag?: Tag): HTMLElementTagNameMap[Tag] {
|
|
47
|
+
if (!html.startsWith(`<${tag}`)) html = `<${tag}>${html}</${tag}>`;
|
|
48
|
+
return new DOMParser().parseFromString(html, 'text/html').body.firstElementChild as HTMLElementTagNameMap[Tag];
|
|
49
|
+
}
|
|
50
|
+
Document.prototype.createElementFromString = createElementFromString;
|
|
51
|
+
|
|
52
|
+
HTMLCollection.prototype.array = function(this: HTMLCollection) {
|
|
53
|
+
return Array.from(this);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const DocumentExtensions = {
|
|
57
|
+
createElement, createElementFromString
|
|
58
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
interface Function {
|
|
3
|
+
/**
|
|
4
|
+
* Checks if obj is a function
|
|
5
|
+
* @param obj Object to check
|
|
6
|
+
*/
|
|
7
|
+
is(obj: any): obj is Function;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function is(obj: any): obj is Function {
|
|
12
|
+
return typeof obj === 'function';
|
|
13
|
+
}
|
|
14
|
+
Function.is = is;
|
|
15
|
+
|
|
16
|
+
export const FunctionExtensions = {
|
|
17
|
+
is
|
|
18
|
+
};
|
package/src/Extensions/Map.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export {}
|
|
2
|
-
|
|
3
1
|
declare global {
|
|
4
2
|
interface Map<K, V> {
|
|
5
3
|
/**
|
|
@@ -38,36 +36,53 @@ declare global {
|
|
|
38
36
|
}
|
|
39
37
|
}
|
|
40
38
|
|
|
41
|
-
|
|
39
|
+
function array<K, V>(this: Map<K, V>): Array<[K, V]> {
|
|
42
40
|
let result = new Array<[K, V]>();
|
|
43
41
|
for (const kvp of this) {
|
|
44
42
|
result.push(kvp);
|
|
45
43
|
}
|
|
46
44
|
return result;
|
|
47
45
|
}
|
|
48
|
-
Map.prototype.
|
|
46
|
+
Map.prototype.array = array;
|
|
47
|
+
|
|
48
|
+
function map<K, V, EK, EV>(this: Map<K, V>, callback: (value: V, key: K, index: number, map: Map<K, V>) => [EK, EV]): Map<EK, EV> {
|
|
49
49
|
return this.array()
|
|
50
50
|
.map(([k, v], i) => callback(v, k, i, this))
|
|
51
51
|
.reduce((map, [key, value]) =>
|
|
52
52
|
map.set(key, value),
|
|
53
53
|
new Map<EK, EV>())
|
|
54
54
|
}
|
|
55
|
-
Map.prototype.
|
|
55
|
+
Map.prototype.map = map;
|
|
56
|
+
|
|
57
|
+
function filter<K, V>(this: Map<K, V>, callback: (value: V, key: K, index: number, map: Map<K, V>) => boolean): Map<K, V> {
|
|
56
58
|
return this.array()
|
|
57
59
|
.filter(([k, v], i) => callback(v, k, i, this))
|
|
58
60
|
.reduce((map, [key, value]) =>
|
|
59
61
|
map.set(key, value),
|
|
60
62
|
new Map<K, V>())
|
|
61
63
|
}
|
|
62
|
-
Map.prototype.
|
|
64
|
+
Map.prototype.filter = filter;
|
|
65
|
+
|
|
66
|
+
function keyArr<K, V>(this: Map<K, V>): Array<K> {
|
|
63
67
|
return this.array().map(([k]) => k);
|
|
64
68
|
}
|
|
65
|
-
Map.prototype.
|
|
69
|
+
Map.prototype.keyArr = keyArr;
|
|
70
|
+
|
|
71
|
+
function valueArr<K, V>(this: Map<K, V>): Array<V> {
|
|
66
72
|
return this.array().map(([_, v]) => v);
|
|
67
73
|
}
|
|
68
|
-
Map.prototype.
|
|
74
|
+
Map.prototype.valueArr = valueArr;
|
|
75
|
+
|
|
76
|
+
function find<K, V>(this: Map<K, V>, callback: (value: V, key: K, index: number, map: Map<K, V>) => boolean) {
|
|
69
77
|
return this.array().find(([k, v], i) => callback(v, k, i, this));
|
|
70
78
|
}
|
|
71
|
-
Map.prototype.
|
|
79
|
+
Map.prototype.find = find;
|
|
80
|
+
|
|
81
|
+
function includes<K, V>(this: Map<K, V>, item: V, fromIndex?: number) {
|
|
72
82
|
return this.valueArr().includes(item, fromIndex);
|
|
83
|
+
}
|
|
84
|
+
Map.prototype.includes = includes;
|
|
85
|
+
|
|
86
|
+
export const MapExtensions = {
|
|
87
|
+
array, map, filter, keyArr, valueArr, find, includes
|
|
73
88
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ValueOf } from "../../Types";
|
|
2
|
+
import { Properties, properties } from "./properties";
|
|
3
|
+
|
|
4
|
+
declare global {
|
|
5
|
+
interface ObjectConstructor {
|
|
6
|
+
/**
|
|
7
|
+
* Destructures object into array of [property, value]
|
|
8
|
+
* @param from Object to destruct
|
|
9
|
+
*/
|
|
10
|
+
array<From extends {} = {}>(from: From): Array<[keyof From, ValueOf<From>]>
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Omits properties from object, but for some reason the correct term is "extract"
|
|
14
|
+
* @param from Object to extract properties from
|
|
15
|
+
* @param props Properties to extract/Omit
|
|
16
|
+
*/
|
|
17
|
+
extract<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Omit<From, Props>
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Pick properties from object, but for some reason the correct term is "exclude"
|
|
21
|
+
* @param from Object to exclude properties from
|
|
22
|
+
* @param props Properties to exclude/pick
|
|
23
|
+
*/
|
|
24
|
+
exclude<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Pick<From, Props>
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Returns true if object is empty
|
|
28
|
+
* @param obj Object to check
|
|
29
|
+
*/
|
|
30
|
+
isNullOrUndefined(obj: any): obj is null | undefined
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Destructures object into array of property keys
|
|
34
|
+
* @param from Object to destruct
|
|
35
|
+
*/
|
|
36
|
+
keysOf<From extends {} = {}>(from: From): Array<keyof From>
|
|
37
|
+
|
|
38
|
+
omit<From extends {}, Exclude extends keyof From>(from: From, ...exclude: Exclude[]): Omit<From, Exclude>;
|
|
39
|
+
|
|
40
|
+
properties: Properties
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function array<From extends {} = {}>(this: object, from: From): Array<[keyof From, ValueOf<From>]> {
|
|
45
|
+
return Object.keysOf(from).map(prop => [prop, from[prop]]) as Array<[keyof From, ValueOf<From>]>;
|
|
46
|
+
}
|
|
47
|
+
Object.array = array;
|
|
48
|
+
|
|
49
|
+
function extract<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Omit<From, Props> {
|
|
50
|
+
// If props are Array<keyof From>, Array<Partial<From>>, or Array<keyof From | Partial<From>>, ensure _props as Array<keyof From>
|
|
51
|
+
const _props = props.map(prop => typeof prop === "object" ? Object.keysOf(prop) : prop).flat();
|
|
52
|
+
_props.forEach(prop => delete from[prop as keyof From]);
|
|
53
|
+
return from;
|
|
54
|
+
}
|
|
55
|
+
Object.extract = extract;
|
|
56
|
+
|
|
57
|
+
function exclude<From extends {}, Props extends keyof From>(from: From, ...props: Array<Props | Partial<From>>): Pick<From, Props> {
|
|
58
|
+
// If props are Array<keyof From>, Array<Partial<From>>, or Array<keyof From | Partial<From>>, ensure _props as Array<keyof From>
|
|
59
|
+
const _props = props.map(prop => typeof prop === "object" ? Object.keysOf(prop) : prop).flat();
|
|
60
|
+
return Object.keysOf(from).reduce((result, prop) => {
|
|
61
|
+
if (_props.includes(prop as Props)) delete result[prop];
|
|
62
|
+
return result;
|
|
63
|
+
}, from);
|
|
64
|
+
}
|
|
65
|
+
Object.exclude = exclude;
|
|
66
|
+
|
|
67
|
+
function isNullOrUndefined(obj: any): obj is null | undefined {
|
|
68
|
+
return obj === null || obj === undefined;
|
|
69
|
+
}
|
|
70
|
+
Object.isNullOrUndefined = isNullOrUndefined;
|
|
71
|
+
|
|
72
|
+
function keysOf<From extends {} = {}>(this: object, from: From): Array<keyof From> {
|
|
73
|
+
return Object.keys(from) as Array<keyof From>;
|
|
74
|
+
}
|
|
75
|
+
Object.keysOf = keysOf;
|
|
76
|
+
|
|
77
|
+
Object.properties = properties;
|
|
78
|
+
|
|
79
|
+
export const ObjectExtensions = {
|
|
80
|
+
properties,
|
|
81
|
+
array, extract, exclude, isNullOrUndefined, keysOf,
|
|
82
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { PropertiesWith, If } from '../../Types';
|
|
2
|
+
import { StringExtensions } from '../String';
|
|
3
|
+
|
|
4
|
+
type PrimitiveMap = {
|
|
5
|
+
string: string;
|
|
6
|
+
number: number;
|
|
7
|
+
boolean: boolean;
|
|
8
|
+
undefined: undefined;
|
|
9
|
+
null: null;
|
|
10
|
+
object: object;
|
|
11
|
+
function: Function;
|
|
12
|
+
any: any;
|
|
13
|
+
Date: Date;
|
|
14
|
+
RegExp: RegExp;
|
|
15
|
+
Promise: Promise<any>;
|
|
16
|
+
Array: Array<any>;
|
|
17
|
+
Map: Map<any, any>;
|
|
18
|
+
Set: Set<any>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Object with getPrimitiveTypes<Source, AllowFunctions extends boolean>(
|
|
23
|
+
* source: Source,
|
|
24
|
+
* allowFunctions: AllowFunctions = false
|
|
25
|
+
* ): Object with properties from source that matches primitive type
|
|
26
|
+
*/
|
|
27
|
+
export type Properties = {
|
|
28
|
+
[Key in keyof PrimitiveMap as `get${Capitalize<Key>}s`]:
|
|
29
|
+
<Source extends {}, AllowFunctions extends boolean = false>(source: Source, withFunctions?: AllowFunctions) =>
|
|
30
|
+
If<AllowFunctions,
|
|
31
|
+
PropertiesWith<PrimitiveMap[Key] | ((...args: any[]) => PrimitiveMap[Key]), Source>,
|
|
32
|
+
PropertiesWith<PrimitiveMap[Key], Source>
|
|
33
|
+
>
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const properties: Properties = [
|
|
37
|
+
'string', 'number', 'boolean', 'undefined', 'null',
|
|
38
|
+
'object', 'function', 'any',
|
|
39
|
+
'Date', 'RegExp', 'Promise', 'Array', 'Map', 'Set'
|
|
40
|
+
].reduce((result, primitive) => {
|
|
41
|
+
result[`get${StringExtensions.toPascalCase.bind(primitive)()}s` as keyof Properties] = function<Source extends {}, AllowFunctions extends boolean = false>(source: Source, withFunctions: AllowFunctions = false as AllowFunctions) {
|
|
42
|
+
return Object.keysOf<Source>(source).reduce((result, key) => {
|
|
43
|
+
if ((source[key] as any).constructor.name === primitive ||
|
|
44
|
+
(withFunctions && typeof source[key] === 'function' && source[key] as any).constructor.name === primitive) {
|
|
45
|
+
result[key] = source[key];
|
|
46
|
+
}
|
|
47
|
+
return result;
|
|
48
|
+
}, {} as any);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}, {} as Properties);
|
package/src/Extensions/String.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import IReplacement from "../Interfaces/IReplacement";
|
|
2
|
-
export {}
|
|
3
2
|
|
|
4
3
|
declare global {
|
|
5
4
|
interface String {
|
|
@@ -26,18 +25,30 @@ declare global {
|
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
|
|
28
|
+
function toPascalCase(this: string) {
|
|
30
29
|
return this.substring(0, 1).toUpperCase() + this.substring(1);
|
|
31
30
|
}
|
|
31
|
+
String.prototype.toPascalCase = toPascalCase;
|
|
32
|
+
|
|
32
33
|
function spaceReplacer(self: string, replacer: string | RegExp, replacement: string) {
|
|
33
34
|
return self.replace(new RegExp(`${typeof replacer == 'string' ? replacer : replacer.source}+`), replacement);
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
|
|
37
|
+
function toSnakeCase(this: string, replaceOptions: IReplacement) {
|
|
36
38
|
return spaceReplacer(this, replaceOptions.replacer || ' ', replaceOptions.replacement || '_')
|
|
37
39
|
}
|
|
38
|
-
String.prototype.
|
|
40
|
+
String.prototype.toSnakeCase = toSnakeCase;
|
|
41
|
+
|
|
42
|
+
function toKebabCase(this: string, replaceOptions: IReplacement) {
|
|
39
43
|
return spaceReplacer(this, replaceOptions.replacer || ' ', replaceOptions.replacement || '-');
|
|
40
44
|
}
|
|
41
|
-
String.prototype.
|
|
45
|
+
String.prototype.toKebabCase = toKebabCase;
|
|
46
|
+
|
|
47
|
+
function clip(this: string, start: number, end?: number) {
|
|
42
48
|
return this.substring(start < 0 ? this.length - start : start, end && end < 0 ? this.length + end : end);
|
|
43
|
-
}
|
|
49
|
+
}
|
|
50
|
+
String.prototype.clip = clip;
|
|
51
|
+
|
|
52
|
+
export const StringExtensions = {
|
|
53
|
+
toPascalCase, toSnakeCase, toKebabCase, clip
|
|
54
|
+
};
|