@open-xamu-co/ui-common-types 1.0.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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2023 @xamu-co
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 @@
1
+ # Xamu UI, types
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@open-xamu-co/ui-common-types",
3
+ "version": "1.0.0",
4
+ "description": "Xamu shared types",
5
+ "author": "@xamu-co",
6
+ "main": "src/index.ts",
7
+ "types": "src/index.ts",
8
+ "type": "module",
9
+ "files": [
10
+ "src/*"
11
+ ],
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/xamu-co/ui.git"
15
+ },
16
+ "keywords": [
17
+ "ts",
18
+ "js",
19
+ "types"
20
+ ],
21
+ "license": "MIT",
22
+ "bugs": {
23
+ "url": "https://github.com/xamu-co/ui/issues"
24
+ },
25
+ "homepage": "https://github.com/xamu-co/ui#readme",
26
+ "publishConfig": {
27
+ "access": "public"
28
+ },
29
+ "scripts": {
30
+ "build": "node -e \"console.log('Build step not required')\"",
31
+ "build:legacy": "rimraf dist && tsc --outDir dist --declaration --emitDeclarationOnly"
32
+ },
33
+ "dependencies": {
34
+ "@open-xamu-co/ui-common-enums": "^1.0.0"
35
+ },
36
+ "devDependencies": {
37
+ "@fortawesome/fontawesome-common-types": "^6.4.0",
38
+ "sweetalert2": "^11.7.5"
39
+ },
40
+ "engines": {
41
+ "node": ">=16.19.0",
42
+ "yarn": ">=1.22.4"
43
+ },
44
+ "browserslist": [
45
+ "defaults"
46
+ ]
47
+ }
package/src/fetch.ts ADDED
@@ -0,0 +1,48 @@
1
+ export type tOrderBy = [string, ("desc" | "asc")?];
2
+
3
+ export interface iPageEdge<T, C extends string | number = string> {
4
+ cursor: C;
5
+ node: T;
6
+ }
7
+
8
+ export interface iPage<T, C extends string | number = string> {
9
+ edges: iPageEdge<T, C>[];
10
+ pageInfo: {
11
+ nextCursor?: C;
12
+ previousCursor?: C;
13
+ hasNextPage: boolean;
14
+ hasPreviousPage: boolean;
15
+ path?: string;
16
+ };
17
+ totalCount: number;
18
+ }
19
+
20
+ export interface iPagination {
21
+ /**
22
+ * Identificador del elemento donde empieza la paginacion
23
+ *
24
+ * starts at 0
25
+ */
26
+ at?: string | number;
27
+ /**
28
+ * Cantidad de elementos (limite)
29
+ */
30
+ first?: number;
31
+ /**
32
+ * JSON string
33
+ * aplica a cualquiera columna
34
+ * ej: ["id", "asc" ], order ascendente de id
35
+ * ej: ["id", "desc" ], order descendente de id
36
+ */
37
+ orderBy?: tOrderBy;
38
+ }
39
+
40
+ /**
41
+ * Hydrate fetch ref (no refresh)
42
+ */
43
+ export type tHydrate<T> = (c: T, e?: unknown) => void;
44
+
45
+ export type iGetPage<T, C extends string | number = string> = (
46
+ hydrate: tHydrate<iPage<T, C> | null>,
47
+ params?: iPagination
48
+ ) => Promise<iPage<T, C>>;
package/src/files.ts ADDED
@@ -0,0 +1,5 @@
1
+ export interface iMime {
2
+ mime: string;
3
+ pattern: number[];
4
+ mask: number[];
5
+ }
package/src/form.ts ADDED
@@ -0,0 +1,148 @@
1
+ import type { IconName } from "@fortawesome/fontawesome-common-types";
2
+
3
+ import { eFormTypeComplex, eFormTypeSimple } from "@open-xamu-co/ui-common-enums";
4
+
5
+ export interface iSelectOption {
6
+ value: string | number;
7
+ alias?: string;
8
+ selected?: boolean;
9
+ /**
10
+ * Font awesome icon
11
+ */
12
+ icon?: IconName;
13
+ /**
14
+ * Color or image url
15
+ */
16
+ pattern?: string;
17
+ placeholder?: string;
18
+ }
19
+
20
+ export interface iIndicative extends iSelectOption {
21
+ code: string;
22
+ number: number;
23
+ }
24
+
25
+ export interface iInvalidInput {
26
+ name: string;
27
+ invalidValue: unknown[];
28
+ }
29
+
30
+ /**
31
+ * Form Values to be send
32
+ */
33
+ export interface iFormResults<T = Record<string, unknown>> {
34
+ values: T;
35
+ invalidInputs: iInvalidInput[];
36
+ }
37
+
38
+ export type tTextInputType = "text" | "email" | "password" | "search" | "url" | "number" | "tel";
39
+
40
+ export type tFormAutocomplete =
41
+ | "off"
42
+ | "on"
43
+ | "name"
44
+ | "honorific-prefix"
45
+ | "given-name"
46
+ | "additional-name"
47
+ | "family-name"
48
+ | "honorific-suffix"
49
+ | "nickname"
50
+ | "email"
51
+ | "username"
52
+ | "new-password"
53
+ | "current-password"
54
+ | "one-time-code"
55
+ | "organization-title"
56
+ | "organization"
57
+ | "street-address"
58
+ | "address-line1"
59
+ | "address-line2"
60
+ | "address-line3"
61
+ | "address-level4"
62
+ | "address-level3"
63
+ | "address-level2"
64
+ | "address-level1"
65
+ | "country"
66
+ | "country-name"
67
+ | "postal-code"
68
+ | "cc-name"
69
+ | "cc-given-name"
70
+ | "cc-additional-name"
71
+ | "cc-family-name"
72
+ | "cc-number"
73
+ | "cc-exp"
74
+ | "cc-exp-month"
75
+ | "cc-exp-year"
76
+ | "cc-csc"
77
+ | "cc-type"
78
+ | "transaction-currency"
79
+ | "transaction-amount"
80
+ | "language"
81
+ | "bday"
82
+ | "bday-day"
83
+ | "bday-month"
84
+ | "bday-year"
85
+ | "sex"
86
+ | "tel"
87
+ | "tel-country-code"
88
+ | "tel-national"
89
+ | "tel-area-code"
90
+ | "tel-local"
91
+ | "tel-extension"
92
+ | "impp"
93
+ | "url";
94
+
95
+ export type iFormIconProps = { brand?: boolean; regular?: boolean };
96
+
97
+ export type tFormIcon = [IconName | undefined, iFormIconProps];
98
+
99
+ export type iFormValue = string | number | boolean | File;
100
+
101
+ /**
102
+ * Simple input
103
+ */
104
+ export interface iFormInputDefault<T extends eFormTypeSimple | eFormTypeComplex = eFormTypeSimple> {
105
+ required?: boolean;
106
+ type?: T;
107
+ options?: (string | number | iSelectOption)[];
108
+ /**
109
+ * String without the dots
110
+ */
111
+ placeholder?: string;
112
+ icon?: IconName | tFormIcon;
113
+ autocomplete?: tFormAutocomplete;
114
+ /**
115
+ * if muliple is set to true this optional value would be the required minimun amount of values
116
+ */
117
+ min?: number;
118
+ /**
119
+ * if multiple is set to true this optional value would be the mandatory maximun amount of values
120
+ */
121
+ max?: number;
122
+ }
123
+
124
+ /**
125
+ * Complex input, sub input support
126
+ */
127
+ export interface iFormInput<V extends iFormValue = iFormValue>
128
+ extends iFormInputDefault<eFormTypeSimple | eFormTypeComplex> {
129
+ name: string;
130
+ /**
131
+ * An array of values to simplify validation
132
+ *
133
+ * @old value
134
+ */
135
+ values?: (V | V[])[];
136
+ defaults?: [iFormInputDefault, iFormInputDefault, ...iFormInputDefault[]];
137
+ /**
138
+ * Visible over the field, should describe it
139
+ */
140
+ title?: string;
141
+ /**
142
+ * input is of type array
143
+ * to require a range or a fixed amount use alongside min & max
144
+ *
145
+ * Ex: { multiple: true, min:3, max:3 } would make 3 values a requirement
146
+ */
147
+ multiple?: boolean;
148
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from "./files.js";
2
+ export * from "./form.js";
3
+ export * from "./transform.js";
4
+ export * from "./styles.js";
5
+ export * from "./props.js";
6
+ export * from "./locale.js";
7
+ export * from "./plugin.js";
8
+ export * from "./fetch.js";
package/src/locale.ts ADDED
@@ -0,0 +1,296 @@
1
+ /**
2
+ * Base locale
3
+ *
4
+ * @localeType
5
+ */
6
+ export interface iLocaleBase {
7
+ /** @example "Yes" */
8
+ yes: string;
9
+ /** @example "No" */
10
+ no: string;
11
+ /** @example "Increase" */
12
+ increase: string;
13
+ /** @example "Decrease" */
14
+ decrease: string;
15
+ /** @example "Couldn't get the data" */
16
+ could_not_get_data: string;
17
+ /** @example "Nothing to show" */
18
+ nothing_to_show: string;
19
+ /** @example "Loading..." */
20
+ loading: string;
21
+ /** @example "Close" */
22
+ close: string;
23
+ /** @example "Ok" */
24
+ ok: string;
25
+ /** @example "See value" */
26
+ see_value: string;
27
+ /** @example "See: \"{name}\"" */
28
+ see_name: string;
29
+ /** @example "Add" */
30
+ add: string;
31
+ /** @example "Clear" */
32
+ clear: string;
33
+ /** @example "* Required. The information provided will be verified." */
34
+ required_verification: string;
35
+ /** @example "Previous" */
36
+ previous: string;
37
+ /** @example "Next" */
38
+ next: string;
39
+ /** @example "Send" */
40
+ send: string;
41
+ /** @example "Select to delete | Delete | Delete {count}" */
42
+ delete: string;
43
+ /** @example "Delete all" */
44
+ delete_all: string;
45
+ /** @example "Pick" */
46
+ pick: string;
47
+ /** @example "Refresh" */
48
+ refresh: string;
49
+ swal: {
50
+ /** @example "Cancel" */
51
+ cancel: string;
52
+ /** @example "Continue" */
53
+ continue: string;
54
+ /** @example "¡Connection error!" */
55
+ connection_error: string;
56
+ /** @example "The server is not responding. Please check your network or try again later" */
57
+ connection_error_message: string;
58
+ /** @example "Retry" */
59
+ connection_error_confirm: string;
60
+ /** @example "Incomplete data" */
61
+ incomplete_data: string;
62
+ /** @example "Fill the data acorddinly" */
63
+ incomplete_data_message: string;
64
+ /** @example "Don't close this window while we finish the task" */
65
+ dont_close_window: string;
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Input locale
71
+ *
72
+ * @localeType
73
+ */
74
+ export interface iLocaleInput {
75
+ /** @example "--SELECT--" */
76
+ select_placeholder: string;
77
+ /** @example "Restablish field" */
78
+ select_restablish_field: string;
79
+ /** @example "Type or Double click for options" */
80
+ select_filter_options: string;
81
+ /** @example "{count} of {amount}" */
82
+ file_one_of_amount: string;
83
+ /** @example "Delete file | Delete files" */
84
+ file_delete_files: string;
85
+ /** @example "Thumbnail" */
86
+ file_thumb: string;
87
+ /** @example "Choose a file | Choose files" */
88
+ file_choose_file: string;
89
+ /** @example "Or drop it here | Or drop them here" */
90
+ file_or_drop_files_here: string;
91
+ /** @example "maximum {size}MB per file" */
92
+ file_max_file_size_mb: string;
93
+ /** @example "Drop file here | Drop files here" */
94
+ file_drop_files_here: string;
95
+ /** @example "Completed" */
96
+ file_completed: string;
97
+ /** @example "Loading file... | Loading files..." */
98
+ file_loading_files: string;
99
+ swal: {
100
+ /** @example "File limit" */
101
+ file_limit: string;
102
+ /** @example "This field only allows {amount} file | This field only allows {amount} files" */
103
+ file_limit_text: string;
104
+ /** @example "Wrong format" */
105
+ file_wrong_format_image: string;
106
+ /** @example "This field only allows image files" */
107
+ file_wrong_format_image_text: string;
108
+ /** @example "File too big" */
109
+ file_too_big: string;
110
+ /** @example "The file exceeds the allowed size" */
111
+ file_too_big_text: string;
112
+ /** @example "Something went wrong" */
113
+ file_unknown_error: string;
114
+ /** @example "There was an error uploding the files, try again later" */
115
+ file_unknown_error_text: string;
116
+ };
117
+ }
118
+
119
+ /**
120
+ * Modal locale
121
+ *
122
+ * @localeType
123
+ */
124
+ export interface iLocaleModal {
125
+ /** @example "Taking too long?" */
126
+ modal_taking_too_long: string;
127
+ swal: {
128
+ /** @example "Unauthorized" */
129
+ modal_unauthorized: string;
130
+ /** @example "You are not allowed to perform this action" */
131
+ modal_unauthorized_text: string;
132
+ };
133
+ }
134
+
135
+ /**
136
+ * Form locale
137
+ *
138
+ * @localeType
139
+ */
140
+ export interface iLocaleForm {
141
+ /** @example "Options are required" */
142
+ form_required_options: string;
143
+ /** @example "No values are required | A value is required | {count} values are required" */
144
+ form_requires_n_values: string;
145
+ /** @example "Look for country" */
146
+ form_country: string;
147
+ /** @example "Look for state" */
148
+ form_state: string;
149
+ /** @example "Look for city" */
150
+ form_city: string;
151
+ /** @example "Desired password" */
152
+ form_desired_password: string;
153
+ /** @example "Confirm password" */
154
+ form_confirm_password: string;
155
+ /** @example "Check password" */
156
+ form_check_password: string;
157
+ /** @example "Password" */
158
+ form_password: string;
159
+ /** @example "E-mail address" */
160
+ form_email: string;
161
+ /** @example "Phone line" */
162
+ form_phone_line: string;
163
+ /** @example "Cellphone number" */
164
+ form_cellphone: string;
165
+ /** @example "ID number" */
166
+ form_id_number: string;
167
+ /** @example "Complete the field" */
168
+ form_complete_the_field: string;
169
+ /** @example "Location" */
170
+ form_location: string;
171
+ /** @example "This field is required" */
172
+ form_required_field: string;
173
+ /** @example "You should use a valid E-mail address" */
174
+ form_use_valid_email: string;
175
+ /** @example "Too short. Use a valid phone number" */
176
+ form_use_valid_phone: string;
177
+ /** @example "You should use a valid cellphone number" */
178
+ form_use_valid_cellphone: string;
179
+ /** @example "The passwords are unmatching" */
180
+ form_unmatching_passwords: string;
181
+ /** @example "Invalid data" */
182
+ form_invalid_data: string;
183
+ // swal: {};
184
+ }
185
+
186
+ /**
187
+ * Table locale
188
+ *
189
+ * @localeType
190
+ */
191
+ export interface iLocaleTable {
192
+ /** @example "See {name}" */
193
+ table_see_values: string;
194
+ /** @example "See: \"{name}\"" */
195
+ table_see_name: string;
196
+ /** @example "Create new" */
197
+ table_create_new: string;
198
+ /** @example "Quantity: {count} */
199
+ table_quantity: string;
200
+ /** @example "Modify" */
201
+ table_modify: string;
202
+ /** @example "Select" */
203
+ table_select: string;
204
+ /** @example "Select all" */
205
+ table_select_all: string;
206
+ /** @example "Update" */
207
+ table_update: string;
208
+ /** @example "Update: \"{name}\"" */
209
+ table_update_name: string;
210
+ /** @example "Delete" */
211
+ table_delete: string;
212
+ /** @example "Delete: \"{name}\"" */
213
+ table_delete_name: string;
214
+ /** @example "Showing: \"{name}\"" */
215
+ table_showing_name: string;
216
+ /** @example "Sort by: \"{name}\"" */
217
+ table_sort_by_name: string;
218
+ /** @example "Duplicate" */
219
+ table_duplicate: string;
220
+ /** @example "Options" */
221
+ table_options: string;
222
+ /** @example "Open URL" */
223
+ table_open_url: string;
224
+ swal: {
225
+ /** @example "Are you sure you want to delete this element?" */
226
+ table_delete_node_title: string;
227
+ /** @example "Remember that you wont be able to recover this element data and you will lost all of your work" */
228
+ table_delete_node_disclaimer: string;
229
+ /** @example "Successfull deletion" */
230
+ table_deleted: string;
231
+ /** @example "Are you sure you want to delete this element? | Are you sure you want to delete these {count} elements?" */
232
+ table_delete_nodes_title: string;
233
+ /** @example "Remember that you wont be able to recover these elements data and you will lost all of your work" */
234
+ table_delete_nodes_disclaimer: string;
235
+ /** @example "The item may not have been deleted | The items may not have been deleted" */
236
+ table_possibly_not_deleted: string;
237
+ /** @example "Successfull update" */
238
+ table_updated: string;
239
+ /** @example "The item may not have been updated | The items may not have been updated" */
240
+ table_possibly_not_updated: string;
241
+ /** @example "Successfull cloning" */
242
+ table_cloned: string;
243
+ /** @example "The item may not have been cloned | The items may not have been cloned" */
244
+ table_possibly_not_cloned: string;
245
+ };
246
+ }
247
+
248
+ /**
249
+ * Pagination locale
250
+ *
251
+ * @localeType
252
+ */
253
+ export interface iLocalePagination {
254
+ /** @example "No items | Single item | {count} items" */
255
+ pagination_items: string;
256
+ /** @example "No pages | Single page | {count} pages" */
257
+ pagination_pages: string;
258
+ /** @example "Order: relevance" */
259
+ pagination_order_relevance: string;
260
+ /** @example "Order: more recent" */
261
+ pagination_order_recent: string;
262
+ /** @example "Order: more older" */
263
+ pagination_order_older: string;
264
+ /** @example "Order: lower price" */
265
+ pagination_order_expensive: string;
266
+ /** @example "Order: high price" */
267
+ pagination_order_cheaper: string;
268
+ /** @example "Order: alphabetically (Asc.)" */
269
+ pagination_order_az: string;
270
+ /** @example "Order: alphabetically (Desc.)" */
271
+ pagination_order_za: string;
272
+ /** @example "Filter by:" */
273
+ pagination_filter_by: string;
274
+ // swal: {};
275
+ }
276
+
277
+ /**
278
+ * Plugin locale
279
+ *
280
+ * @localeType
281
+ */
282
+ export type tPluginLocale = iLocaleBase &
283
+ iLocaleInput &
284
+ iLocaleModal &
285
+ iLocaleForm &
286
+ iLocaleTable &
287
+ iLocalePagination;
288
+
289
+ /**
290
+ * Plugin locale key union
291
+ *
292
+ * @localeType
293
+ */
294
+ export type tPluginLocaleKey =
295
+ | Exclude<keyof tPluginLocale, "swal">
296
+ | `swal.${keyof Required<tPluginLocale>["swal"]}`;
package/src/plugin.ts ADDED
@@ -0,0 +1,118 @@
1
+ import { componentNames } from "@open-xamu-co/ui-common-enums";
2
+
3
+ import type { tPluginLocale } from "./locale.js";
4
+ import type { SweetAlertOptions } from "sweetalert2";
5
+
6
+ export type tComponent = (typeof componentNames)[number];
7
+
8
+ export type tSupportedLangs =
9
+ | "kr"
10
+ | "pt"
11
+ | "nl"
12
+ | "hr"
13
+ | "fa"
14
+ | "de"
15
+ | "es"
16
+ | "en"
17
+ | "fr"
18
+ | "ja"
19
+ | "it"
20
+ | "cn"
21
+ | "tr";
22
+
23
+ export interface iPluginOptions<ComponentType = unknown> {
24
+ /**
25
+ * Use web components
26
+ */
27
+ webComponents?: boolean;
28
+ /**
29
+ * Register all or specific components globally
30
+ *
31
+ * @default true
32
+ */
33
+ globalComponents?: boolean | tComponent[];
34
+ /**
35
+ * Components prefix
36
+ *
37
+ * @default "xamu"
38
+ * @example xamu-component-name or XamuComponentName
39
+ */
40
+ componentPrefix?: string;
41
+ /**
42
+ * Router component
43
+ * If a router is used this component is required for buttons to work
44
+ */
45
+ routerComponent?: ComponentType | string;
46
+ /**
47
+ * Image component
48
+ * Optional image optimization component
49
+ */
50
+ imageComponent?: ComponentType | string;
51
+ /**
52
+ * Host that contain images
53
+ * Treat the url within them as images
54
+ *
55
+ * @example ["lh3.googleusercontent.com"]
56
+ * */
57
+ imageHosts?: string[];
58
+ /**
59
+ * Locales language code
60
+ * @default en - English locale
61
+ *
62
+ * Used to localize external data
63
+ */
64
+ lang?: tSupportedLangs;
65
+ /**
66
+ * Global locale values
67
+ * @default en - English locale
68
+ *
69
+ * You can implement your own or find more locale at "@open-xamu-co/ui-common-helpers/locale"
70
+ */
71
+ locale?: tPluginLocale;
72
+ mediaQueryPixels?: {
73
+ /**
74
+ * Laptop media query limit (max-width) in px
75
+ *
76
+ * @default 1080
77
+ * @mediaQuery
78
+ */
79
+ laptop?: number;
80
+ /**
81
+ * Tablet media query limit (max-width) in px
82
+ *
83
+ * @default 768
84
+ * @mediaQuery
85
+ */
86
+ tablet?: number;
87
+ /**
88
+ * Mobile media query limit (max-width) in px
89
+ *
90
+ * @default 576
91
+ * @mediaQuery
92
+ */
93
+ mobile?: number;
94
+ };
95
+ swal?: {
96
+ overrides?: SweetAlertOptions;
97
+ preventOverrides?: SweetAlertOptions;
98
+ loaderOverrides?: SweetAlertOptions;
99
+ };
100
+ /**
101
+ * Iso2 code for the default country
102
+ *
103
+ * When a country is provided forms will omit that field
104
+ */
105
+ country?: string;
106
+ /**
107
+ * Disable automatic animations
108
+ */
109
+ disableAutoAnimate?: boolean;
110
+ /**
111
+ * Use pro Font Awesome icons (regular, light)
112
+ */
113
+ fontAwesomePro?: boolean;
114
+ /**
115
+ * Default pagination limit
116
+ */
117
+ first?: number;
118
+ }
package/src/props.ts ADDED
@@ -0,0 +1,3 @@
1
+ export type tProp<T extends string = string> = T | Record<T, boolean>;
2
+ export type tProps<T extends string = string> = tProp<T> | tProp<T>[];
3
+ export type tPropsModifier<T extends string = string> = boolean | tProps<T>;
package/src/styles.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { eColors } from "@open-xamu-co/ui-common-enums";
2
+
3
+ /**
4
+ * Union of supported colors.
5
+ * @colors
6
+ */
7
+ export type tThemeModifier = (typeof eColors)[keyof typeof eColors]; // to union
8
+ export type tThemeTuple = [tThemeModifier, tThemeModifier?];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Allows prefixing & suffixing of object properties
3
+ *
4
+ * @see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-1.html#key-remapping-in-mapped-types
5
+ */
6
+ export type tPropertyMapping<
7
+ T extends Record<string, unknown>,
8
+ Prefix extends string = "",
9
+ Suffix extends string = "",
10
+ > = {
11
+ [K in keyof T as `${Prefix}${Capitalize<string & K>}${Capitalize<string & Suffix>}`]: T[K];
12
+ };