kempo 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.
Files changed (194) hide show
  1. package/.gitattributes +2 -0
  2. package/LICENSE +21 -0
  3. package/README.md +2 -0
  4. package/dist/components/Card.js +1 -0
  5. package/dist/components/CodeEditor.js +1 -0
  6. package/dist/components/Component.js +1 -0
  7. package/dist/components/Dialog.js +1 -0
  8. package/dist/components/FocusCapture.js +1 -0
  9. package/dist/components/Icon.js +1 -0
  10. package/dist/components/Import.js +1 -0
  11. package/dist/components/LazyComponent.js +1 -0
  12. package/dist/components/ReactiveComponent.js +1 -0
  13. package/dist/components/ReactiveLazyComponent.js +1 -0
  14. package/dist/components/Resize.js +1 -0
  15. package/dist/components/Search.js +1 -0
  16. package/dist/components/ShowMore.js +1 -0
  17. package/dist/components/SideMenu.js +1 -0
  18. package/dist/components/Split.js +1 -0
  19. package/dist/components/Tabs.js +1 -0
  20. package/dist/components/ThemeSwitcher.js +1 -0
  21. package/dist/components/Timestamp.js +1 -0
  22. package/dist/components/WebSnippetEditor.js +1 -0
  23. package/dist/index.js +1 -0
  24. package/dist/kempo-hljs.css +1 -0
  25. package/dist/kempo-styles.css +1 -0
  26. package/dist/kempo-vars.css +1 -0
  27. package/dist/kempo.css +1 -0
  28. package/dist/kempo.js +1 -0
  29. package/dist/utils/cli.js +1 -0
  30. package/dist/utils/cookie.js +1 -0
  31. package/dist/utils/debounce.js +1 -0
  32. package/dist/utils/drag.js +1 -0
  33. package/dist/utils/element.js +1 -0
  34. package/dist/utils/formatTimestamp.js +1 -0
  35. package/dist/utils/fuzzyMatch.js +1 -0
  36. package/dist/utils/getPreferredTheme.js +1 -0
  37. package/dist/utils/loadCss.js +1 -0
  38. package/dist/utils/loadScript.js +1 -0
  39. package/dist/utils/object.js +1 -0
  40. package/dist/utils/string.js +1 -0
  41. package/dist/utils/toFunction.js +1 -0
  42. package/dist/utils/type.js +1 -0
  43. package/dist/utils/waitFrames.js +1 -0
  44. package/docs/components/_template.html +22 -0
  45. package/docs/components/card.html +35 -0
  46. package/docs/components/codeeditor.html +29 -0
  47. package/docs/components/component.html +88 -0
  48. package/docs/components/dialog.html +89 -0
  49. package/docs/components/icon.html +73 -0
  50. package/docs/components/import.html +34 -0
  51. package/docs/components/lazycomponent.html +50 -0
  52. package/docs/components/resize.html +107 -0
  53. package/docs/components/show-more.html +92 -0
  54. package/docs/components/sidemenu.html +97 -0
  55. package/docs/components/split.html +70 -0
  56. package/docs/components/tabs.html +33 -0
  57. package/docs/components/websnippeteditor.html +42 -0
  58. package/docs/index.html +17 -0
  59. package/docs/kempo/components/Card.js +1 -0
  60. package/docs/kempo/components/CodeEditor.js +1 -0
  61. package/docs/kempo/components/Collapse.js +1 -0
  62. package/docs/kempo/components/Component.js +1 -0
  63. package/docs/kempo/components/Dialog.js +1 -0
  64. package/docs/kempo/components/FocusCapture.js +1 -0
  65. package/docs/kempo/components/Icon.js +1 -0
  66. package/docs/kempo/components/Import.js +1 -0
  67. package/docs/kempo/components/LazyComponent.js +1 -0
  68. package/docs/kempo/components/ReactiveComponent.js +1 -0
  69. package/docs/kempo/components/ReactiveLazyComponent.js +1 -0
  70. package/docs/kempo/components/Resize.js +1 -0
  71. package/docs/kempo/components/Search.js +1 -0
  72. package/docs/kempo/components/ShowMore.js +1 -0
  73. package/docs/kempo/components/SideMenu.js +1 -0
  74. package/docs/kempo/components/Split.js +1 -0
  75. package/docs/kempo/components/Tabs.js +1 -0
  76. package/docs/kempo/components/ThemeSwitcher.js +1 -0
  77. package/docs/kempo/components/Timestamp.js +1 -0
  78. package/docs/kempo/components/WebSnippetEditor.js +1 -0
  79. package/docs/kempo/icons/arrow-down-double.svg +1 -0
  80. package/docs/kempo/icons/arrow-up-double.svg +1 -0
  81. package/docs/kempo/icons/close.svg +2 -0
  82. package/docs/kempo/icons/compare.svg +1 -0
  83. package/docs/kempo/icons/dark-mode.svg +1 -0
  84. package/docs/kempo/icons/delete.svg +1 -0
  85. package/docs/kempo/icons/filter-off.svg +1 -0
  86. package/docs/kempo/icons/filter.svg +1 -0
  87. package/docs/kempo/icons/light-mode.svg +1 -0
  88. package/docs/kempo/icons/menu.svg +1 -0
  89. package/docs/kempo/icons/pause.svg +1 -0
  90. package/docs/kempo/icons/play.svg +1 -0
  91. package/docs/kempo/icons/search.svg +1 -0
  92. package/docs/kempo/icons/settings.svg +1 -0
  93. package/docs/kempo/icons/storage.svg +1 -0
  94. package/docs/kempo/icons/trash-x.svg +1 -0
  95. package/docs/kempo/index.js +1 -0
  96. package/docs/kempo/kempo-hljs.css +1 -0
  97. package/docs/kempo/kempo-styles.css +1 -0
  98. package/docs/kempo/kempo-vars.css +1 -0
  99. package/docs/kempo/kempo.css +1 -0
  100. package/docs/kempo/kempo.js +1 -0
  101. package/docs/kempo/utils/cli.js +1 -0
  102. package/docs/kempo/utils/cookie.js +1 -0
  103. package/docs/kempo/utils/debounce.js +1 -0
  104. package/docs/kempo/utils/drag.js +1 -0
  105. package/docs/kempo/utils/element.js +1 -0
  106. package/docs/kempo/utils/formatTimestamp.js +1 -0
  107. package/docs/kempo/utils/fuzzyMatch.js +1 -0
  108. package/docs/kempo/utils/getPreferredTheme.js +1 -0
  109. package/docs/kempo/utils/loadCss.js +1 -0
  110. package/docs/kempo/utils/loadScript.js +1 -0
  111. package/docs/kempo/utils/object.js +1 -0
  112. package/docs/kempo/utils/string.js +1 -0
  113. package/docs/kempo/utils/toFunction.js +1 -0
  114. package/docs/kempo/utils/type.js +1 -0
  115. package/docs/kempo/utils/waitFrames.js +1 -0
  116. package/docs/nav-1.inc.html +66 -0
  117. package/docs/nav.inc.html +66 -0
  118. package/docs/search.json +94 -0
  119. package/docs/styles/_template.html +22 -0
  120. package/docs/styles/borders-spacing.html +193 -0
  121. package/docs/styles/buttons.html +113 -0
  122. package/docs/styles/colors.html +65 -0
  123. package/docs/styles/displays-layouts.html +156 -0
  124. package/docs/styles/embed-1.html +35 -0
  125. package/docs/styles/inputs.html +89 -0
  126. package/docs/styles/tables.html +143 -0
  127. package/docs/styles/typography.html +116 -0
  128. package/icons/arrow-down-double.svg +1 -0
  129. package/icons/arrow-up-double.svg +1 -0
  130. package/icons/close.svg +2 -0
  131. package/icons/compare.svg +1 -0
  132. package/icons/dark-mode.svg +1 -0
  133. package/icons/delete.svg +1 -0
  134. package/icons/filter-off.svg +1 -0
  135. package/icons/filter.svg +1 -0
  136. package/icons/light-mode.svg +1 -0
  137. package/icons/menu.svg +1 -0
  138. package/icons/pause.svg +1 -0
  139. package/icons/play.svg +1 -0
  140. package/icons/search.svg +1 -0
  141. package/icons/settings.svg +1 -0
  142. package/icons/storage.svg +1 -0
  143. package/icons/trash-x.svg +1 -0
  144. package/kempo/components/Card.js +65 -0
  145. package/kempo/components/CodeEditor.js +141 -0
  146. package/kempo/components/Component.js +109 -0
  147. package/kempo/components/Dialog.js +277 -0
  148. package/kempo/components/FocusCapture.js +30 -0
  149. package/kempo/components/Icon.js +60 -0
  150. package/kempo/components/Import.js +40 -0
  151. package/kempo/components/LazyComponent.js +40 -0
  152. package/kempo/components/ReactiveComponent.js +11 -0
  153. package/kempo/components/ReactiveLazyComponent.js +11 -0
  154. package/kempo/components/Resize.js +168 -0
  155. package/kempo/components/Search.js +136 -0
  156. package/kempo/components/ShowMore.js +82 -0
  157. package/kempo/components/SideMenu.js +156 -0
  158. package/kempo/components/Split.js +133 -0
  159. package/kempo/components/Tabs.js +254 -0
  160. package/kempo/components/ThemeSwitcher.js +77 -0
  161. package/kempo/components/Timestamp.js +25 -0
  162. package/kempo/components/WebSnippetEditor.js +159 -0
  163. package/kempo/kempo-hljs.css +145 -0
  164. package/kempo/kempo-styles.css +893 -0
  165. package/kempo/kempo-vars.css +154 -0
  166. package/kempo/kempo.js +48 -0
  167. package/kempo/utils/cli.js +54 -0
  168. package/kempo/utils/cookie.js +16 -0
  169. package/kempo/utils/debounce.js +9 -0
  170. package/kempo/utils/drag.js +74 -0
  171. package/kempo/utils/element.js +69 -0
  172. package/kempo/utils/formatTimestamp.js +11 -0
  173. package/kempo/utils/fuzzyMatch.js +55 -0
  174. package/kempo/utils/getPreferredTheme.js +1 -0
  175. package/kempo/utils/loadCss.js +10 -0
  176. package/kempo/utils/loadScript.js +10 -0
  177. package/kempo/utils/object.js +177 -0
  178. package/kempo/utils/string.js +54 -0
  179. package/kempo/utils/toFunction.js +24 -0
  180. package/kempo/utils/type.js +8 -0
  181. package/kempo/utils/waitFrames.js +17 -0
  182. package/package.json +33 -0
  183. package/scripts/build.js +131 -0
  184. package/scripts/docs.js +14 -0
  185. package/test/components/SuiteList.js +26 -0
  186. package/test/components/Test.js +357 -0
  187. package/test/index.html +49 -0
  188. package/test/index.js +25 -0
  189. package/test/suite.html +45 -0
  190. package/test/suites.inc.html +4 -0
  191. package/test/tests/components/Component.test.js +138 -0
  192. package/test/tests/utils/cli.test.js +113 -0
  193. package/test/tests/utils/cookie.test.js +87 -0
  194. package/test/tests/utils/debounce.test.js +71 -0
@@ -0,0 +1,154 @@
1
+ :root {
2
+ --ff_body: "Helvetica Neue", Helvetica, Arial, sans-serif;
3
+ --ff_heading: "Helvetica Neue", Helvetica, Arial, sans-serif;
4
+ --ff_mono: Consolas, monaco, monospace;
5
+ --fs_base: 16px;
6
+ --fs_small: calc(0.6 * var(--fs_base));
7
+ --fs_large: calc(1.5 * var(--fs_base));
8
+ --fs_h6: var(--fs_base);
9
+ --fs_h5: calc(1.25 * var(--fs_base));
10
+ --fs_h4: calc(1.5 * var(--fs_base));
11
+ --fs_h3: calc(1.75 * var(--fs_base));
12
+ --fs_h2: calc(2 * var(--fs_base));
13
+ --fs_h1: calc(2.5 * var(--fs_base));
14
+ --fw_base: 400;
15
+ --fw_bold: 700;
16
+ --spacer: 1rem;
17
+ --spacer_h: calc(0.5 * var(--spacer));
18
+ --spacer_q: calc(0.25 * var(--spacer));
19
+ --line-height: 1.35em;
20
+ --container_width: 90rem;
21
+ --animation_ms: 256ms;
22
+ --radius: 0.25rem;
23
+ --link_decoration: underline;
24
+ --input_border_width: 2px;
25
+ }
26
+
27
+ :root,
28
+ [theme="light"] {
29
+ color-scheme: light;
30
+ --c_bg: #f9f9f9;
31
+ --c_bg__inv: #333;
32
+ --c_bg__alt: #eee;
33
+ --c_overscroll: white;
34
+ --c_border: #ccc;
35
+ --c_border__inv: var(--d_c_bg_border);
36
+ --c_primary: #36f;
37
+ --c_primary__hover: #14d;
38
+ --c_secondary: #93f;
39
+ --c_secondary__hover: #71d;
40
+ --c_success: #080;
41
+ --c_success__hover: #060;
42
+ --c_warning: #f60;
43
+ --c_warning__hover: #d40;
44
+ --c_danger: #f03;
45
+ --c_danger__hover: #d01;
46
+ --c_input_accent: #36f;
47
+ --c_highlight: rgba(41, 100, 210, 0.25);
48
+ --tc: rgba(0, 0, 0, 0.93);
49
+ --tc_dark: var(--tc);
50
+ --tc_light: rgba(255, 255, 255, 0.93);
51
+ --tc_inv: var(--tc_light);
52
+ --tc_muted: rgba(0, 0, 0, 0.5);
53
+ --tc_on_primary: var(--tc_light);
54
+ --tc_on_secondary: var(--tc_light);
55
+ --tc_on_success: var(--tc_light);
56
+ --tc_on_warning: var(--tc_light);
57
+ --tc_on_danger: var(--tc_light);
58
+ --c_overlay: rgba(0, 0, 0, 0.5);
59
+ --tc_primary: #36f;
60
+ --tc_secondary: #93f;
61
+ --tc_success: #080;
62
+ --tc_warning: #f60;
63
+ --tc_danger: #f03;
64
+ --btn_box_shadow: 0 0 0 transparent;
65
+ --btn_box_shadow__hover: 0 0 0 transparent;
66
+ --btn_border: transparent;
67
+ --btn_bg: #ddd;
68
+ --btn_bg__hover: #ccc;
69
+ --btn_tc: rgba(0, 0, 0, 0.93);
70
+ --btn_transparent__hover: rgba(0, 0, 0, 0.05);
71
+ --tc_link: var(--tc_primary);
72
+ --tc_link__hover: var(--tc_secondary);
73
+ --tc_link__inv: var(--tc_primary__inv);
74
+ --tc_link__inv__hover: var(--tc_secondary__inv);
75
+ --focus_shadow: 0 0 2px 2px var(--c_primary);
76
+ --focus_shadow_on_primary: 0 0 2px 2px var(--tc_on_primary);
77
+ --input_bg: white;
78
+ --input_tc: rgba(0, 0, 0, 0.93);
79
+ --drop_shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.333);
80
+ }
81
+ [theme="dark"] {
82
+ color-scheme: dark;
83
+ --c_bg: #333;
84
+ --c_bg__inv: #f9f9f9;
85
+ --c_bg__alt: #222;
86
+ --c_overscroll: black;
87
+ --c_border: #777;
88
+ --c_border__inv: #ccc;
89
+ --c_primary: #36f;
90
+ --c_primary__hover: #14d;
91
+ --c_secondary: #93f;
92
+ --c_secondary__hover: #71d;
93
+ --c_success: #080;
94
+ --c_success__hover: #060;
95
+ --c_warning: #f60;
96
+ --c_warning__hover: #d40;
97
+ --c_danger: #f03;
98
+ --c_danger__hover: #d01;
99
+ --c_input_accent: #36f;
100
+ --c_highlight: rgba(0, 89, 255, 0.25);
101
+ --tc: rgba(255, 255, 255, 0.93);
102
+ --tc_dark: rgba(0, 0, 0, 0.93);
103
+ --tc_light: var(--tc);
104
+ --tc_inv: var(--tc_dark);
105
+ --tc_muted: rgba(255, 255, 255, 0.5);
106
+ --tc_on_primary: var(--tc);
107
+ --tc_on_secondary: var(--tc);
108
+ --tc_on_success: var(--tc);
109
+ --tc_on_warning: var(--tc);
110
+ --tc_on_danger: var(--tc);
111
+ --c_overlay: rgba(0, 0, 0, 0.5);
112
+ --tc_primary: #8ab4f8;
113
+ --tc_secondary: #b6f;
114
+ --tc_success: #6b6;
115
+ --tc_warning: #f93;
116
+ --tc_danger: #f57;
117
+ --btn_bg: #aaa;
118
+ --btn_bg__hover: #bbb;
119
+ --btn_tc: rgba(0, 0, 0, 0.93);
120
+ --btn_transparent__hover: rgba(255, 255, 255, 0.05);
121
+ --btn_box_shadow: 0 0 0 transparent;
122
+ --btn_box_shadow__hover: 0 0 0 transparent;
123
+ --btn_border: transparent;
124
+ --tc_link: var(--tc_primary);
125
+ --tc_link__hover: var(--tc_secondary);
126
+ --tc_link__inv: var(--tc_primary__inv);
127
+ --tc_link__inv__hover: var(--tc_secondary__inv);
128
+ --focus_shadow: 0 0 2px 2px var(--c_primary);
129
+ --focus_shadow_on_primary: 0 0 2px 2px var(--tc_on_primary);
130
+ --input_bg: white;
131
+ --input_tc: rgba(0, 0, 0, 0.93);
132
+ --ff_body: "Helvetica Neue", Helvetica, Arial, sans-serif;
133
+ --ff_heading: "Helvetica Neue", Helvetica, Arial, sans-serif;
134
+ --ff_mono: Consolas, monaco, monospace;
135
+ --fs_base: 16px;
136
+ --fs_h6: var(--fs_base);
137
+ --fs_h5: calc(1.25 * var(--fs_base));
138
+ --fs_h4: calc(1.5 * var(--fs_base));
139
+ --fs_h3: calc(1.75 * var(--fs_base));
140
+ --fs_h2: calc(2 * var(--fs_base));
141
+ --fs_h1: calc(2.5 * var(--fs_base));
142
+ --fw_base: 400;
143
+ --fw_bold: 700;
144
+ --spacer: 1rem;
145
+ --spacer_h: calc(0.5 * var(--spacer));
146
+ --spacer_q: calc(0.25 * var(--spacer));
147
+ --line-height: 1.35em;
148
+ --container_width: 90rem;
149
+ --animation_ms: 256ms;
150
+ --radius: 0.25rem;
151
+ --drop_shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.25);
152
+ --link_decoration: underline;
153
+ --input_border_width: 2px;
154
+ }
package/kempo/kempo.js ADDED
@@ -0,0 +1,48 @@
1
+ const components = {
2
+ 'k-card': 'Card',
3
+ 'k-code-editor': 'CodeEditor',
4
+ 'k-dialog': 'Dialog',
5
+ 'k-icon': 'Icon',
6
+ 'k-import': 'Import',
7
+ 'k-resize': 'Resize',
8
+ 'k-search': 'Search',
9
+ 'k-show-more': 'ShowMore',
10
+ 'k-side-menu': 'SideMenu',
11
+ 'k-split': 'Split',
12
+ 'k-tabs': 'Tabs',
13
+ 'k-web-snippet-editor': 'WebSnippetEditor'
14
+ }
15
+ const lookFor = new Set(Object.keys(components));
16
+ window.kempo = Object.assign({}, {
17
+ pathToRoot: './',
18
+ pathToKempoFromRoot: './kempo/',
19
+ pathToIconsFromRoot: './kempo/icons/',
20
+ autoLoadComponents: () => {
21
+ lookFor.forEach( async component => {
22
+ if(document.querySelector(component)){
23
+ const path = `${kempo.pathToRoot}${kempo.pathToKempoFromRoot}components/${components[component]}.js`;
24
+ console.log(path);
25
+ import(path);
26
+ lookFor.delete(component);
27
+ }
28
+ });
29
+ },
30
+ _darkModeQuery: window.matchMedia('(prefers-color-scheme: dark)'),
31
+ _theme: 'auto',
32
+ _themeListener: (e) => {
33
+ if(window.kempo._theme === 'auto'){
34
+ document.documentElement.setAttribute('theme', e.matches?'dark':'light');
35
+ }
36
+ },
37
+ setTheme: (theme) => {
38
+ window.kempo._theme = theme;
39
+ if(window.kempo._theme === 'auto'){
40
+ document.documentElement.setAttribute('theme', window.kempo._darkModeQuery.matches?'dark':'light');
41
+ } else {
42
+ document.documentElement.setAttribute('theme', theme);
43
+ }
44
+ }
45
+ }, window.kempo || {});
46
+ window.kempo.autoLoadComponents();
47
+ window.kempo._darkModeQuery.addEventListener('change', window.kempo._themeListener);
48
+ window.kempo.setTheme(document.documentElement.getAttribute('theme') || 'auto');
@@ -0,0 +1,54 @@
1
+ const args = {};
2
+ let win = {};
3
+ if(typeof(window) !== 'undefined'){
4
+ win = window;
5
+ } else if(typeof(global) !== 'undefined'){
6
+ win = global;
7
+ }
8
+ win.log = (...messages) => {
9
+ if(args.debug){
10
+ console.log(...messages);
11
+ }
12
+ }
13
+
14
+ export default (shortMap = {
15
+ d: 'debug'
16
+ }) => {
17
+ let name = '';
18
+ let values = [];
19
+ const save = () => {
20
+ if(name){
21
+ if(values.length === 0){ // flag
22
+ args[name] = true;
23
+ } else if(values.length === 1){ // single value
24
+ args[name] = values[0];
25
+ } else { // multiple values
26
+ args[name] = values;
27
+ }
28
+ }
29
+ }
30
+
31
+ for(let i=2; i<process.argv.length; i++){
32
+ const arg = process.argv[i];
33
+ if(arg.startsWith('-')){
34
+ // new argument, save the last one
35
+ save()
36
+ // start a new one
37
+ if(arg.startsWith('--')){ // long form
38
+ name = arg.slice(2);
39
+ } else { // short form
40
+ name = arg.slice(1);
41
+ if(shortMap[name]){
42
+ name = shortMap[name];
43
+ }
44
+ }
45
+ values = [];
46
+ } else {
47
+ // value
48
+ values.push(arg);
49
+ }
50
+ }
51
+ // save last arg
52
+ save();
53
+ return args;
54
+ }
@@ -0,0 +1,16 @@
1
+ const saveCookie = (name, value, minutes = 30 * 24 * 60, path = '/') => {
2
+ const expires = new Date(Date.now() + minutes * 60 * 1000);
3
+ document.cookie = `${name}=${value};expires=${expires.toUTCString()};path=${path}`;
4
+ };
5
+
6
+ const getCookie = (name) => {
7
+ const cookies = document.cookie.split(';').map(cookie => cookie.trim().split('='));
8
+ const cookie = cookies.find(cookie => cookie[0] === name);
9
+ return cookie ? cookie[1] : null;
10
+ };
11
+
12
+ const deleteCookie = (name) => {
13
+ document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/`;
14
+ };
15
+
16
+ export { saveCookie, getCookie, deleteCookie };
@@ -0,0 +1,9 @@
1
+ function debounce(func, timeout = 300){
2
+ let timer;
3
+ return (...args) => {
4
+ clearTimeout(timer);
5
+ timer = setTimeout(() => { func.apply(this, args); }, timeout);
6
+ };
7
+ }
8
+
9
+ export default debounce;
@@ -0,0 +1,74 @@
1
+ export default (options = {}) => {
2
+ let startX, startY, timeoutId;
3
+
4
+ const {
5
+ element = () => {},
6
+ callback = () => {},
7
+ startCallback = () => {},
8
+ moveCallback = () => {},
9
+ endCallback = () => {},
10
+ preventScroll = false
11
+ } = options;
12
+
13
+ const dragMove = (event) => {
14
+ if (preventScroll) {
15
+ event.preventDefault(); // prevent drag scrolling
16
+ }
17
+ clearTimeout(timeoutId);
18
+ const pageX = event.pageX || event.touches[0].pageX;
19
+ const pageY = event.pageY || event.touches[0].pageY;
20
+ const diff = {
21
+ x: pageX - startX,
22
+ y: pageY - startY,
23
+ ...options
24
+ };
25
+ callback(diff);
26
+ moveCallback(diff);
27
+ };
28
+
29
+ const dragEnd = ({ pageX, pageY }) => {
30
+ clearTimeout(timeoutId);
31
+ const diff = {
32
+ x: pageX - startX,
33
+ y: pageY - startY,
34
+ ...options
35
+ };
36
+ callback(diff);
37
+ endCallback(diff);
38
+ removeListeners();
39
+ };
40
+
41
+ const dragStart = (event) => {
42
+ clearTimeout(timeoutId);
43
+ startX = event.pageX || event.touches[0].pageX;;
44
+ startY = event.pageY || event.touches[0].pageY;;
45
+ const diff = {
46
+ x: 0,
47
+ y: 0,
48
+ ...options
49
+ };
50
+ startCallback(diff);
51
+ window.addEventListener('mousemove', dragMove, {passive:!preventScroll});
52
+ window.addEventListener('mouseup', dragEnd, {passive:!preventScroll});
53
+ window.addEventListener('touchmove', dragMove, {passive:!preventScroll});
54
+ window.addEventListener('touchend', dragEnd, {passive:!preventScroll});
55
+ // window.addEventListener('mouseout', dragEnd);
56
+ };
57
+
58
+ const removeListeners = () => {
59
+ window.removeEventListener('mousemove', dragMove);
60
+ window.removeEventListener('mouseup', dragEnd);
61
+ window.removeEventListener('touchmove', dragMove);
62
+ window.removeEventListener('touchend', dragEnd);
63
+ // window.removeEventListener('mouseout', dragEnd);
64
+ };
65
+
66
+ element.addEventListener('mousedown', dragStart, {passive:!preventScroll});
67
+ element.addEventListener('touchstart', dragStart, {passive:!preventScroll});
68
+
69
+ // Return removeListeners for cleanup
70
+ return ()=>{
71
+ element.removeEventListener('mousedown', dragStart);
72
+ removeListeners();
73
+ }
74
+ };
@@ -0,0 +1,69 @@
1
+ import waitFrames from './waitFrames.js';
2
+
3
+ export const onEvent = (element, events, handler, scope = document) => {
4
+ if(element instanceof EventTarget){
5
+ events.toLowerCase().split(' ').forEach( event => {
6
+ element.addEventListener(event, handler);
7
+ });
8
+ } else if(element instanceof NodeList || element instanceof Array){
9
+ element.forEach( el => onEvent(el, events, handler));
10
+ } else if(typeof(element) == 'string'){
11
+ scope.querySelectorAll(element).forEach( el => onEvent(el, events, handler));
12
+ }
13
+ }
14
+ export const offEvent = (element, events, handler, scope = document) => {
15
+ if(element instanceof EventTarget){
16
+ events.toLowerCase().split(' ').forEach( event => {
17
+ element.removeEventListener(event, handler);
18
+ });
19
+ } else if(element instanceof NodeList || element instanceof Array){
20
+ element.forEach( el => offEvent(el, events, handler));
21
+ } else if(typeof(element) == 'string'){
22
+ scope.querySelectorAll(element).forEach( el => offEvent(el, events, handler));
23
+ }
24
+ }
25
+ export const dispatchEvent = (element, events, detail, scope = document) => {
26
+ if(element instanceof EventTarget){
27
+ events.toLowerCase().split(' ').forEach( event => {
28
+ element.dispatchEvent(new CustomEvent(event, { detail } ));
29
+ });
30
+ } else if(element instanceof NodeList || element instanceof Array){
31
+ element.forEach( el => dispatchEvent(el, events, handler));
32
+ } else if(typeof(element) == 'string'){
33
+ scope.querySelectorAll(element).forEach( el => dispatchEvent(el, events, handler));
34
+ }
35
+ }
36
+ export const isInView = async (element) => {
37
+ await waitFrames(2);
38
+ const rect = element.getBoundingClientRect();
39
+ const windowHeight = window.innerHeight || document.documentElement.clientHeight;
40
+ const windowWidth = window.innerWidth || document.documentElement.clientWidth;
41
+ if (
42
+ rect.bottom < 0 ||
43
+ rect.top > windowHeight ||
44
+ rect.right < 0 ||
45
+ rect.left > windowWidth
46
+ ) {
47
+ return false;
48
+ }
49
+ while (element) {
50
+ const style = getComputedStyle(element);
51
+ if (style.display === 'none' || style.visibility === 'hidden') {
52
+ return false;
53
+ }
54
+ element = element.parentElement;
55
+ }
56
+ return true;
57
+ }
58
+ export const firstFocusable = (scope) => {
59
+ return scope.querySelector('a[href]:not([disabled]), button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([disabled]):not([tabindex="-1"])');
60
+ }
61
+ export const setProp = (element, prop, value, scope = document) => {
62
+ if(element instanceof HTMLElement){
63
+ element[prop] = value;
64
+ } else if(element instanceof NodeList || element instanceof Array){
65
+ [...element].forEach(element => dispatchEvent(element, prop, value));
66
+ } else if(typeof(element) === 'string'){
67
+ dispatchEvent(scope.querySelectorAll(element), prop, value);
68
+ }
69
+ }
@@ -0,0 +1,11 @@
1
+ export default (timestamp, forceLocale) => {
2
+ return Intl.DateTimeFormat(forceLocale || navigator.language, {
3
+ year: 'numeric',
4
+ month: '2-digit',
5
+ day: '2-digit',
6
+ hour: '2-digit',
7
+ minute: '2-digit',
8
+ second: '2-digit',
9
+ millisecond: '3-digit'
10
+ }).format(new Date(parseInt(timestamp)));
11
+ }
@@ -0,0 +1,55 @@
1
+ /*
2
+ This module was created by Chat GPT using the following prompts:
3
+ Write me a function in JS, that takes two strings, and does a fuzzy match to see if the first string contains the second string, this way if the second string has a typo or misspelling in it we still get a partial match. Make it return a score between 0 and 10 that indicates the strength of the match, with a perfect 10 being a perfect match, and a 0 being no characters match with the threashold greater than 3. Give a higher score if the match is towards the beginning of the first string.
4
+ */
5
+
6
+ export const fuzzyMatch = (str1, str2) => {
7
+ const levenshteinDistance = (s1, s2) => {
8
+ const m = s1.length;
9
+ const n = s2.length;
10
+ const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0));
11
+
12
+ for (let i = 0; i <= m; i++) {
13
+ for (let j = 0; j <= n; j++) {
14
+ if (i === 0) dp[i][j] = j;
15
+ else if (j === 0) dp[i][j] = i;
16
+ else dp[i][j] = Math.min(
17
+ dp[i - 1][j - 1] + (s1.charAt(i - 1) === s2.charAt(j - 1) ? 0 : 1),
18
+ dp[i][j - 1] + 1,
19
+ dp[i - 1][j] + 1
20
+ );
21
+ }
22
+ }
23
+
24
+ return dp[m][n];
25
+ };
26
+
27
+ const fuzzyThreshold = 3;
28
+
29
+ const distance = levenshteinDistance(str1.toLowerCase(), str2.toLowerCase());
30
+
31
+ if (distance === 0) {
32
+ return 10; // Perfect match
33
+ }
34
+
35
+ const score = Math.max(0, 10 - distance / fuzzyThreshold);
36
+
37
+ const positionScore = Math.min((str1.length - distance) / str1.length, 1);
38
+
39
+ return Math.round(score * 5 + positionScore * 5); // Scale to 0-10
40
+ };
41
+
42
+ /*
43
+ Chat GPT Prompt
44
+ Can you write another function that takes an array of strings, and a string, creates a score based on how well the second string matches each of the function you created above. Then find the average non-zero match of the second string to the items in the array
45
+ */
46
+ export const fuzzyMatchArray = (array, targetString) => {
47
+ const nonZeroScores = array
48
+ .map(currentString => fuzzyMatch(currentString, targetString))
49
+ .filter(score => score !== 0);
50
+ if (nonZeroScores.length === 0) {
51
+ return 0; // Return 0 if there are no non-zero scores
52
+ }
53
+ const averageScore = nonZeroScores.reduce((sum, score) => sum + score, 0) / nonZeroScores.length;
54
+ return averageScore;
55
+ };
@@ -0,0 +1 @@
1
+ export default () => window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
@@ -0,0 +1,10 @@
1
+ export default (url, type = 'stylesheet') => {
2
+ return new Promise((resolve, reject) => {
3
+ const link = document.createElement('link');
4
+ link.rel = type;
5
+ link.href = url;
6
+ link.onload = resolve;
7
+ link.onerror = reject;
8
+ document.head.appendChild(link);
9
+ });
10
+ }
@@ -0,0 +1,10 @@
1
+ export default (scriptUrl, type = 'module') => {
2
+ return new Promise((resolve, reject) => {
3
+ const script = document.createElement('script');
4
+ script.type = type;
5
+ script.src = scriptUrl;
6
+ script.onload = resolve;
7
+ script.onerror = reject;
8
+ document.head.appendChild(script);
9
+ });
10
+ }