kempo-ui 0.0.3 → 0.0.4

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 (137) hide show
  1. package/.github/workflows/publish-major.yml +39 -0
  2. package/.github/workflows/publish-minor.yml +39 -0
  3. package/.github/workflows/{publish-npm.yml → publish-patch.yml} +1 -1
  4. package/.vscode/settings.json +2 -0
  5. package/dist/kempo-hljs.css +1 -0
  6. package/dist/src/components/Accordion.js +36 -0
  7. package/dist/src/components/Card.js +37 -0
  8. package/dist/src/components/Collapsible.js +41 -0
  9. package/dist/src/components/ContentSlider.js +44 -0
  10. package/dist/src/components/Dialog.js +113 -0
  11. package/dist/src/components/Icon.js +2 -2
  12. package/dist/src/components/PersistantCollapsible.js +1 -0
  13. package/dist/src/components/PhotoViewer.js +135 -0
  14. package/dist/src/components/Resize.js +96 -0
  15. package/dist/src/components/ShowMore.js +42 -0
  16. package/dist/src/components/SideMenu.js +1 -1
  17. package/dist/src/components/Split.js +84 -0
  18. package/dist/src/components/Tabs.js +155 -0
  19. package/dist/src/components/Tags.js +69 -0
  20. package/dist/src/components/ThemeSwitcher.js +23 -0
  21. package/dist/src/components/Timestamp.js +1 -0
  22. package/dist/src/utils/debounce.js +1 -0
  23. package/dist/src/utils/drag.js +1 -0
  24. package/dist/src/utils/formatTimestamp.js +1 -0
  25. package/dist/src/utils/propConverters.js +1 -0
  26. package/dist/src/utils/watchWindowSize.js +1 -0
  27. package/docs/components/accordion.html +69 -25
  28. package/docs/components/card.html +6 -5
  29. package/docs/components/collapsible.html +198 -0
  30. package/docs/components/content-slider.html +56 -26
  31. package/docs/components/dialog.html +54 -48
  32. package/docs/components/focus-capture.html +2 -3
  33. package/docs/components/icon.html +5 -8
  34. package/docs/components/import.html +1 -6
  35. package/docs/components/persistant-collapsible.html +123 -0
  36. package/docs/components/photo-viewer.html +226 -0
  37. package/docs/components/resize.html +44 -18
  38. package/docs/components/show-more.html +12 -6
  39. package/docs/components/side-menu.html +3 -12
  40. package/docs/components/split.html +26 -5
  41. package/docs/components/tablePagination.html +4 -4
  42. package/docs/components/tableRecordFiltering.html +16 -3
  43. package/docs/components/tableRecordSelection.html +2 -2
  44. package/docs/components/tabs.html +24 -7
  45. package/docs/components/tags.html +24 -8
  46. package/docs/components/theme-switcher.html +3 -6
  47. package/docs/components/timestamp.html +20 -24
  48. package/docs/components/toast.html +23 -32
  49. package/docs/components/toggle.html +4 -3
  50. package/docs/kempo-hljs.css +1 -0
  51. package/docs/media/civic.jpg +0 -0
  52. package/docs/media/corvette.jpg +0 -0
  53. package/docs/media/evo.jpg +0 -0
  54. package/docs/media/gtr.jpg +0 -0
  55. package/docs/media/nsx.jpg +0 -0
  56. package/docs/nav.inc.html +11 -17
  57. package/docs/src/components/Accordion.js +36 -0
  58. package/docs/src/components/Card.js +37 -0
  59. package/docs/src/components/Collapsible.js +41 -0
  60. package/docs/src/components/ContentSlider.js +44 -0
  61. package/docs/src/components/Dialog.js +113 -0
  62. package/docs/src/components/Icon.js +2 -2
  63. package/docs/src/components/PersistantCollapsible.js +1 -0
  64. package/docs/src/components/PhotoViewer.js +135 -0
  65. package/docs/src/components/Resize.js +96 -0
  66. package/docs/src/components/ShowMore.js +42 -0
  67. package/docs/src/components/SideMenu.js +1 -1
  68. package/docs/src/components/Split.js +84 -0
  69. package/docs/src/components/Tabs.js +155 -0
  70. package/docs/src/components/Tags.js +69 -0
  71. package/docs/src/components/ThemeSwitcher.js +23 -0
  72. package/docs/src/components/Timestamp.js +1 -0
  73. package/docs/src/utils/debounce.js +1 -0
  74. package/docs/src/utils/drag.js +1 -0
  75. package/docs/src/utils/formatTimestamp.js +1 -0
  76. package/docs/src/utils/propConverters.js +1 -0
  77. package/docs/src/utils/watchWindowSize.js +1 -0
  78. package/docs/utils/debounce.html +78 -0
  79. package/docs/utils/drag.html +104 -0
  80. package/docs/utils/formatTimestamp.html +114 -0
  81. package/docs/utils/propConverters.html +132 -0
  82. package/docs/utils/watchWindowSize.html +166 -0
  83. package/icons/error.svg +1 -1
  84. package/icons/warning.svg +1 -1
  85. package/package.json +1 -1
  86. package/scripts/build.js +1 -1
  87. package/scripts/docs.js +4 -2
  88. package/src/components/Accordion.js +229 -0
  89. package/src/components/Collapsible.js +109 -0
  90. package/src/components/ContentSlider.js +205 -0
  91. package/src/components/Dialog.js +368 -0
  92. package/src/components/PersistantCollapsible.js +69 -0
  93. package/src/components/PhotoViewer.js +368 -0
  94. package/src/components/Resize.js +210 -0
  95. package/src/components/ShadowComponent.js +3 -1
  96. package/src/components/ShowMore.js +109 -0
  97. package/src/components/Sortable.js +193 -0
  98. package/src/components/Split.js +192 -0
  99. package/src/components/Table.js +1202 -0
  100. package/src/components/Tabs.js +428 -0
  101. package/src/components/Tags.js +253 -0
  102. package/src/components/Timestamp.js +31 -0
  103. package/src/components/Toast.js +454 -0
  104. package/src/components/Toggle.js +173 -0
  105. package/src/components/tableControls/DeleteRecord.js +29 -0
  106. package/src/components/tableControls/Edit.js +88 -0
  107. package/src/components/tableControls/ExportCSV.js +71 -0
  108. package/src/components/tableControls/ExportJson.js +55 -0
  109. package/src/components/tableControls/FieldSortHide.js +76 -0
  110. package/src/components/tableControls/Filters.js +114 -0
  111. package/src/components/tableControls/FirstPage.js +65 -0
  112. package/src/components/tableControls/HiddenCount.js +45 -0
  113. package/src/components/tableControls/Hide.js +34 -0
  114. package/src/components/tableControls/LastPage.js +65 -0
  115. package/src/components/tableControls/NextPage.js +65 -0
  116. package/src/components/tableControls/PageSelect.js +109 -0
  117. package/src/components/tableControls/PageSize.js +68 -0
  118. package/src/components/tableControls/PrevPage.js +65 -0
  119. package/src/components/tableControls/Search.js +58 -0
  120. package/src/components/tableControls/ShowAll.js +34 -0
  121. package/src/components/tableControls/TableControl.js +105 -0
  122. package/src/utils/debounce.js +9 -0
  123. package/src/utils/drag.js +80 -0
  124. package/src/utils/formatTimestamp.js +27 -0
  125. package/src/utils/toTitleCase.js +9 -0
  126. package/src/utils/watchWindowSize.js +16 -0
  127. package/dist/src/utils/cli.js +0 -1
  128. package/dist/src/utils/fs-utils.js +0 -1
  129. package/docs/components/component.html +0 -90
  130. package/docs/components/directory-viewer.html +0 -90
  131. package/docs/components/lazy-component.html +0 -84
  132. package/docs/components/reactive-component.html +0 -69
  133. package/docs/components/reactive-lazy-component.html +0 -69
  134. package/docs/components/search.html +0 -102
  135. package/docs/components/sortable.html +0 -96
  136. package/src/utils/cli.js +0 -43
  137. package/src/utils/fs-utils.js +0 -41
@@ -0,0 +1,109 @@
1
+ import TableControl from './TableControl.js';
2
+ import { html, css } from '../../lit-all.min.js';
3
+
4
+ export default class PageSelect extends TableControl {
5
+ static properties = {
6
+ ...TableControl.properties,
7
+ currentPage: { type: Number, state: true },
8
+ totalPages: { type: Number, state: true }
9
+ };
10
+
11
+ constructor() {
12
+ super({
13
+ maxWidth: null
14
+ });
15
+ this.currentPage = 1;
16
+ this.totalPages = 1;
17
+ }
18
+
19
+ /*
20
+ Lifecycle Callbacks
21
+ */
22
+
23
+ connectedCallback() {
24
+ super.connectedCallback();
25
+ this.onTableEvent('pageChange', this.handlePageChange);
26
+ this.onTableEvent('pageSizeChange', this.handlePageSizeChange);
27
+ this.onTableEvent('pageCountChanged', this.handlePageCountChange);
28
+ }
29
+
30
+ disconnectedCallback() {
31
+ super.disconnectedCallback();
32
+ if(this.table){
33
+ this.table.removeEventListener('pageChange', this.handlePageChange);
34
+ this.table.removeEventListener('pageSizeChange', this.handlePageSizeChange);
35
+ this.table.removeEventListener('pageCountChanged', this.handlePageCountChange);
36
+ }
37
+ }
38
+
39
+ /*
40
+ Event Handlers
41
+ */
42
+
43
+ handlePageChange = () => {
44
+ if(this.table){
45
+ this.currentPage = this.table.getCurrentPage();
46
+ }
47
+ };
48
+
49
+ handlePageSizeChange = () => {
50
+ if(this.table){
51
+ this.currentPage = this.table.getCurrentPage();
52
+ this.totalPages = this.table.getTotalPages();
53
+ }
54
+ };
55
+
56
+ handlePageCountChange = () => {
57
+ if(this.table){
58
+ this.totalPages = this.table.getTotalPages();
59
+ }
60
+ };
61
+
62
+ handleSelectChange = e => {
63
+ if(this.table){
64
+ this.table.setPage(parseInt(e.target.value));
65
+ }
66
+ };
67
+
68
+ /*
69
+ Rendering Logic
70
+ */
71
+
72
+ render() {
73
+ if(!this.table){
74
+ return html`<div>No table found</div>`;
75
+ }
76
+
77
+ const options = [];
78
+ for(let i = 1; i <= this.totalPages; i++){
79
+ options.push(html`<option value="${i}" ?selected="${i === this.currentPage}">Page ${i}</option>`);
80
+ }
81
+
82
+ return html`
83
+ <div class="page-select">
84
+ <select class="no-btn ph b r" @change="${this.handleSelectChange}" ?disabled="${this.totalPages <= 1}">
85
+ ${options}
86
+ </select>
87
+ <label> out of ${this.totalPages}</label>
88
+ </div>
89
+ `;
90
+ }
91
+
92
+ static styles = css`
93
+ ${TableControl.styles}
94
+
95
+ .page-select {
96
+ display: flex;
97
+ align-items: center;
98
+ gap: 0.25rem;
99
+ white-space: nowrap;
100
+ }
101
+
102
+ label {
103
+ padding: 0;
104
+ margin: 0;
105
+ }
106
+ `;
107
+ }
108
+
109
+ customElements.define('k-tc-page-select', PageSelect);
@@ -0,0 +1,68 @@
1
+ import TableControl from './TableControl.js';
2
+ import { html } from '../../lit-all.min.js';
3
+
4
+ export default class PageSize extends TableControl {
5
+ constructor() {
6
+ super({
7
+ maxWidth: null
8
+ });
9
+ this.pageChangeHandler = () => this.requestUpdate();
10
+ this.pageSizeChangeHandler = () => this.requestUpdate();
11
+ }
12
+
13
+ /*
14
+ Lifecycle Callbacks
15
+ */
16
+
17
+ connectedCallback() {
18
+ super.connectedCallback();
19
+ this.onTableEvent('pageChange', this.pageChangeHandler);
20
+ this.onTableEvent('pageSizeChange', this.pageSizeChangeHandler);
21
+ }
22
+
23
+ disconnectedCallback() {
24
+ super.disconnectedCallback();
25
+ if(this.table){
26
+ this.table.removeEventListener('pageChange', this.pageChangeHandler);
27
+ this.table.removeEventListener('pageSizeChange', this.pageSizeChangeHandler);
28
+ }
29
+ }
30
+
31
+ /*
32
+ Event Handlers
33
+ */
34
+
35
+ handleChange = e => {
36
+ if(this.table){
37
+ this.table.setPageSize(parseInt(e.target.value));
38
+ }
39
+ };
40
+
41
+ /*
42
+ Utility Functions
43
+ */
44
+
45
+ get currentPageSize() {
46
+ return this.table ? this.table.getPageSize() : 10;
47
+ }
48
+
49
+ get pageSizeOptions() {
50
+ return this.table ? this.table.pageSizeOptions : [10, 25, 50, 100, 500];
51
+ }
52
+
53
+ /*
54
+ Rendering Logic
55
+ */
56
+
57
+ render() {
58
+ return html`
59
+ <select class="no-btn ph b r" @change="${this.handleChange}">
60
+ ${this.pageSizeOptions.map(size =>
61
+ html`<option value="${size}" ?selected="${size === this.currentPageSize}">${size} per page</option>`
62
+ )}
63
+ </select>
64
+ `;
65
+ }
66
+ }
67
+
68
+ customElements.define('k-tc-page-size', PageSize);
@@ -0,0 +1,65 @@
1
+ import TableControl from './TableControl.js';
2
+ import { html } from '../../lit-all.min.js';
3
+ import '../Icon.js';
4
+
5
+ export default class PrevPage extends TableControl {
6
+ constructor() {
7
+ super();
8
+ this.pageChangeHandler = () => this.requestUpdate();
9
+ }
10
+
11
+ /*
12
+ Lifecycle Callbacks
13
+ */
14
+
15
+ connectedCallback() {
16
+ super.connectedCallback();
17
+ if(this.table){
18
+ this.table.addEventListener('pageChange', this.pageChangeHandler);
19
+ }
20
+ }
21
+
22
+ disconnectedCallback() {
23
+ super.disconnectedCallback();
24
+ if(this.table){
25
+ this.table.removeEventListener('pageChange', this.pageChangeHandler);
26
+ }
27
+ }
28
+
29
+ /*
30
+ Event Handlers
31
+ */
32
+
33
+ handleClick = () => {
34
+ if(this.table){
35
+ this.table.prevPage();
36
+ }
37
+ };
38
+
39
+ /*
40
+ Utility Functions
41
+ */
42
+
43
+ get isDisabled() {
44
+ if(!this.table) return true;
45
+ return this.table.getCurrentPage() === 1;
46
+ }
47
+
48
+ /*
49
+ Rendering Logic
50
+ */
51
+
52
+ render() {
53
+ return html`
54
+ <button
55
+ class="no-btn icon-btn"
56
+ ?disabled="${this.isDisabled}"
57
+ @click="${this.handleClick}"
58
+ >
59
+ <k-icon name="chevron-left"></k-icon>
60
+ </button>
61
+ `;
62
+ }
63
+ }
64
+
65
+ customElements.define('k-tc-prev-page', PrevPage);
@@ -0,0 +1,58 @@
1
+ import TableControl from './TableControl.js';
2
+ import { html } from '../../lit-all.min.js';
3
+ import debounce from '../../utils/debounce.js';
4
+
5
+ export default class Search extends TableControl {
6
+ /*
7
+ Properties
8
+ */
9
+ static properties = {
10
+ searchTerm: { type: String }
11
+ };
12
+
13
+ /*
14
+ Constructor
15
+ */
16
+ constructor() {
17
+ super({ maxWidth: 200 });
18
+ this.debouncedSearch = debounce(this.performSearch, 200);
19
+ }
20
+
21
+ /*
22
+ Event Handlers
23
+ */
24
+ handleInput = (e) => {
25
+ this.searchTerm = e.target.value;
26
+ this.debouncedSearch();
27
+ };
28
+
29
+ /*
30
+ Methods
31
+ */
32
+ performSearch = () => {
33
+ if(!this.table) return;
34
+
35
+ if(!this.searchTerm || this.searchTerm.length < 3){
36
+ this.table.showAllRecords();
37
+ } else {
38
+ this.table.search(this.searchTerm);
39
+ }
40
+ };
41
+
42
+ /*
43
+ Rendering
44
+ */
45
+ render() {
46
+ return html`
47
+ <input
48
+ type="search"
49
+ placeholder="Search"
50
+ class="px pyh"
51
+ .value="${this.searchTerm || ''}"
52
+ @input="${this.handleInput}"
53
+ />
54
+ `;
55
+ }
56
+ }
57
+
58
+ customElements.define('k-tc-search', Search);
@@ -0,0 +1,34 @@
1
+ import TableControl from './TableControl.js';
2
+ import { html } from '../../lit-all.min.js';
3
+ import '../Icon.js';
4
+
5
+ export default class ShowAll extends TableControl {
6
+ /*
7
+ Constructor
8
+ */
9
+ constructor() {
10
+ super({ maxWidth: 40 });
11
+ }
12
+
13
+ /*
14
+ Event Handlers
15
+ */
16
+ handleShowAll = () => {
17
+ if(this.table){
18
+ this.table.showAllRecords();
19
+ }
20
+ };
21
+
22
+ /*
23
+ Rendering
24
+ */
25
+ render() {
26
+ return html`
27
+ <button class="no-btn icon-btn" @click="${this.handleShowAll}">
28
+ <k-icon name="show"></k-icon>
29
+ </button>
30
+ `;
31
+ }
32
+ }
33
+
34
+ customElements.define('k-tc-show-all', ShowAll);
@@ -0,0 +1,105 @@
1
+ import ShadowComponent from '../ShadowComponent.js';
2
+ import { html, css } from '../../lit-all.min.js';
3
+
4
+ export default class TableControl extends ShadowComponent {
5
+ /*
6
+ Properties
7
+ */
8
+ static properties = {
9
+ maxWidth: { type: Number, reflect: true, attribute: 'max-width' }
10
+ };
11
+
12
+ /*
13
+ Constructor
14
+ */
15
+ constructor({
16
+ maxWidth = 40
17
+ } = {}) {
18
+ super();
19
+ this.maxWidth = maxWidth;
20
+ }
21
+
22
+ /*
23
+ Lifecycle Callbacks
24
+ */
25
+ updated(changedProperties) {
26
+ super.updated(changedProperties);
27
+ if(changedProperties.has('maxWidth')){
28
+ if(this.maxWidth){
29
+ this.style.setProperty('--max-width', `${this.maxWidth}px`);
30
+ } else {
31
+ this.style.removeProperty('--max-width');
32
+ }
33
+ }
34
+ }
35
+
36
+ firstUpdated() {
37
+ if(this.maxWidth){
38
+ this.style.setProperty('--max-width', `${this.maxWidth}px`);
39
+ } else {
40
+ this.style.removeProperty('--max-width');
41
+ }
42
+ }
43
+
44
+ /*
45
+ Getters for Table Integration
46
+ */
47
+ get table() {
48
+ if (this.getRootNode() instanceof ShadowRoot) {
49
+ return this.getRootNode().host.closest('k-table');
50
+ } else {
51
+ return this.closest('k-table');
52
+ }
53
+ }
54
+
55
+ get record() {
56
+ if (this.getRootNode() instanceof ShadowRoot) {
57
+ const $record = this.closest('.record');
58
+ if ($record) {
59
+ const index = $record.dataset.index;
60
+ if (index !== undefined) {
61
+ return this.table.records[index];
62
+ }
63
+ }
64
+ }
65
+ return false;
66
+ }
67
+
68
+ /*
69
+ Table Event Handling
70
+ */
71
+ async onTableEvent(eventNames, handler) {
72
+ // Wait for k-table to be defined before trying to find it
73
+ await customElements.whenDefined('k-table');
74
+
75
+ if(this.table){
76
+ const events = eventNames.split(' ');
77
+ events.forEach(eventName => {
78
+ this.table.addEventListener(eventName, handler);
79
+ });
80
+ this.requestUpdate(); // Force update after table is found
81
+ }
82
+ }
83
+
84
+ /*
85
+ Styles
86
+ */
87
+ static styles = css`
88
+ :host {
89
+ display: inline-flex;
90
+ }
91
+
92
+ .icon-btn {
93
+ display: inline-flex !important;
94
+ align-items: center;
95
+ justify-content: center;
96
+ width: 40px;
97
+ height: 40px;
98
+ }
99
+ .icon-btn:disabled {
100
+ opacity: 0.6;
101
+ }
102
+ `;
103
+ }
104
+
105
+ customElements.define('k-table-control', TableControl);
@@ -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,80 @@
1
+ /*
2
+ Drag Utility
3
+ */
4
+ export default (options = {}) => {
5
+ let startX, startY, timeoutId;
6
+
7
+ const {
8
+ element,
9
+ callback = () => {},
10
+ startCallback = () => {},
11
+ moveCallback = () => {},
12
+ endCallback = () => {},
13
+ preventScroll = false
14
+ } = options;
15
+
16
+ const dragMove = (event) => {
17
+ if(preventScroll) {
18
+ event.preventDefault(); // prevent drag scrolling
19
+ }
20
+ clearTimeout(timeoutId);
21
+ const pageX = event.pageX || event.touches[0].pageX;
22
+ const pageY = event.pageY || event.touches[0].pageY;
23
+ const diff = {
24
+ x: pageX - startX,
25
+ y: pageY - startY,
26
+ ...options
27
+ };
28
+ callback(diff);
29
+ moveCallback(diff);
30
+ };
31
+
32
+ const dragEnd = (event) => {
33
+ clearTimeout(timeoutId);
34
+ const pageX = event.pageX || (event.changedTouches && event.changedTouches[0].pageX) || 0;
35
+ const pageY = event.pageY || (event.changedTouches && event.changedTouches[0].pageY) || 0;
36
+ const diff = {
37
+ x: pageX - startX,
38
+ y: pageY - startY,
39
+ ...options
40
+ };
41
+ callback(diff);
42
+ endCallback(diff);
43
+ removeListeners();
44
+ };
45
+
46
+ const dragStart = (event) => {
47
+ if(event.button && event.button !== 0) return; // Only left click for mouse
48
+
49
+ clearTimeout(timeoutId);
50
+ startX = event.pageX || event.touches[0].pageX;
51
+ startY = event.pageY || event.touches[0].pageY;
52
+ const diff = {
53
+ x: 0,
54
+ y: 0,
55
+ ...options
56
+ };
57
+ startCallback(diff);
58
+ window.addEventListener('mousemove', dragMove, { passive: !preventScroll });
59
+ window.addEventListener('mouseup', dragEnd, { passive: !preventScroll });
60
+ window.addEventListener('touchmove', dragMove, { passive: !preventScroll });
61
+ window.addEventListener('touchend', dragEnd, { passive: !preventScroll });
62
+ };
63
+
64
+ const removeListeners = () => {
65
+ window.removeEventListener('mousemove', dragMove);
66
+ window.removeEventListener('mouseup', dragEnd);
67
+ window.removeEventListener('touchmove', dragMove);
68
+ window.removeEventListener('touchend', dragEnd);
69
+ };
70
+
71
+ element.addEventListener('mousedown', dragStart, { passive: !preventScroll });
72
+ element.addEventListener('touchstart', dragStart, { passive: !preventScroll });
73
+
74
+ // Return cleanup function
75
+ return () => {
76
+ element.removeEventListener('mousedown', dragStart);
77
+ element.removeEventListener('touchstart', dragStart);
78
+ removeListeners();
79
+ };
80
+ };
@@ -0,0 +1,27 @@
1
+ export default (timestamp, format, forceLocale) => {
2
+ const date = new Date(parseInt(timestamp));
3
+ if (format) {
4
+ const pad = (num, size) => ('000' + num).slice(size * -1);
5
+ const tokens = {
6
+ YYYY: date.getFullYear(),
7
+ YY: String(date.getFullYear()).slice(-2),
8
+ MM: pad(date.getMonth() + 1, 2),
9
+ M: date.getMonth() + 1,
10
+ DD: pad(date.getDate(), 2),
11
+ D: date.getDate(),
12
+ hh: pad(date.getHours(), 2),
13
+ h: date.getHours(),
14
+ mm: pad(date.getMinutes(), 2),
15
+ m: date.getMinutes(),
16
+ ss: pad(date.getSeconds(), 2),
17
+ s: date.getSeconds(),
18
+ iiii: pad(date.getMilliseconds(), 3),
19
+ iii: pad(date.getMilliseconds(), 3),
20
+ ii: pad(date.getMilliseconds(), 2),
21
+ i: date.getMilliseconds()
22
+ };
23
+ return format.replace(/YYYY|YY|MM|M|DD|D|hh|h|mm|m|ss|s|iiii|iii|ii|i/g, (matched) => tokens[matched]);
24
+ } else {
25
+ return date.toLocaleString(forceLocale || navigator.language);
26
+ }
27
+ }
@@ -0,0 +1,9 @@
1
+ const toTitleCase = str =>
2
+ str
3
+ .replace(/([A-Z])/g, ' $1')
4
+ .split(/[\s_-]+/)
5
+ .filter(word => word.length > 0)
6
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
7
+ .join(' ');
8
+
9
+ export default toTitleCase;
@@ -0,0 +1,16 @@
1
+ import debounce from './debounce.js';
2
+
3
+ const handlers = new Set();
4
+ window.addEventListener('resize', debounce(() => {
5
+ const width = window.innerWidth;
6
+ handlers.forEach((handler) => handler(width));
7
+ }));
8
+
9
+ export const watchWindowSize = (handler) => {
10
+ handlers.add(handler);
11
+ return window.innerWidth;
12
+ };
13
+
14
+ export const unwatchWindowSize = (handler) => {
15
+ handlers.delete(handler);
16
+ };
@@ -1 +0,0 @@
1
- import{spawn}from"child_process";export const getArgs=r=>{const e={},s=process.argv.slice(2);for(let o=0;o<s.length;o++){const t=s[o];if(t.startsWith("-")){const n=t.replace(/^-+/,""),c=r[n]||n,i=s[o+1];i&&!i.startsWith("-")?(e[c]=i,o++):e[c]=!0}}return e};export const runChildNodeProcess=r=>{const e=spawn("node",[r],{stdio:"inherit",shell:!0});return new Promise((r,s)=>{e.on("close",e=>{0===e?r():s(new Error(`Process exited with code ${e}`))}),e.on("error",s)})};
@@ -1 +0,0 @@
1
- import fs from"fs/promises";import path from"path";export const ensureDir=async r=>{try{await fs.mkdir(r,{recursive:!0})}catch(r){if("EEXIST"!==r.code)throw r}};export const copyDir=async(r,t)=>{await ensureDir(t);const i=await fs.readdir(r,{withFileTypes:!0});for(const a of i){const i=path.join(r,a.name),o=path.join(t,a.name);a.isDirectory()?await copyDir(i,o):await fs.copyFile(i,o)}};export const emptyDir=async r=>{try{const t=await fs.readdir(r);await Promise.all(t.map(t=>fs.rm(path.join(r,t),{recursive:!0,force:!0})))}catch(r){if("ENOENT"!==r.code)throw r}};