kempo-ui 0.1.6 → 0.2.2

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 (119) hide show
  1. package/.github/skills/highlight-code/SKILL.md +22 -6
  2. package/.github/skills/new-component/SKILL.md +68 -4
  3. package/AGENTS.md +11 -0
  4. package/bin/highlight_code.js +7 -15
  5. package/dist/components/Aside.js +326 -0
  6. package/dist/components/Dialog.js +1 -1
  7. package/dist/components/Dropdown.js +1 -1
  8. package/dist/components/Main.js +2 -2
  9. package/dist/components/Nav.js +27 -0
  10. package/dist/components/PhotoViewer.js +1 -1
  11. package/dist/components/ShadowComponent.js +1 -1
  12. package/dist/components/ThemeSwitcher.js +1 -0
  13. package/dist/components/Toast.js +1 -1
  14. package/docs/components/accordion.html +4 -3
  15. package/docs/components/aside-items.html +43 -0
  16. package/docs/components/aside-menu.html +43 -0
  17. package/docs/components/aside-push.html +26 -0
  18. package/docs/components/aside.html +567 -0
  19. package/docs/components/card.html +4 -3
  20. package/docs/components/color-picker.html +4 -3
  21. package/docs/components/content-slider.html +4 -3
  22. package/docs/components/dialog.html +4 -3
  23. package/docs/components/dropdown.html +4 -3
  24. package/docs/components/filter-list.html +4 -3
  25. package/docs/components/focus-capture.html +6 -5
  26. package/docs/components/html-editor.html +5 -4
  27. package/docs/components/hybrid-component.html +5 -4
  28. package/docs/components/icon.html +4 -3
  29. package/docs/components/import.html +5 -4
  30. package/docs/components/light-component.html +4 -3
  31. package/docs/components/nav.html +117 -0
  32. package/docs/components/photo-viewer.html +5 -4
  33. package/docs/components/resize.html +5 -4
  34. package/docs/components/shadow-component.html +4 -3
  35. package/docs/components/show-more.html +5 -4
  36. package/docs/components/sortable.html +4 -3
  37. package/docs/components/spinner.html +4 -3
  38. package/docs/components/split.html +5 -4
  39. package/docs/components/table.html +4 -3
  40. package/docs/components/tableControls.html +4 -3
  41. package/docs/components/tableCustomFields.html +4 -3
  42. package/docs/components/tableFetchRecords.html +5 -4
  43. package/docs/components/tableFieldSortHide.html +5 -4
  44. package/docs/components/tablePagination.html +4 -3
  45. package/docs/components/tableRecordEditing.html +4 -3
  46. package/docs/components/tableRecordFiltering.html +5 -4
  47. package/docs/components/tableRecordHiding.html +4 -3
  48. package/docs/components/tableRecordSearching.html +5 -4
  49. package/docs/components/tableRecordSelection.html +4 -3
  50. package/docs/components/tableRowControls.html +4 -3
  51. package/docs/components/tableServerSync.html +5 -4
  52. package/docs/components/tableSorting.html +5 -4
  53. package/docs/components/tabs.html +4 -3
  54. package/docs/components/tags.html +4 -3
  55. package/docs/components/theme-select.html +4 -3
  56. package/docs/components/theme-switcher.html +5 -4
  57. package/docs/components/timestamp.html +4 -3
  58. package/docs/components/toast.html +4 -3
  59. package/docs/components/toggle.html +5 -4
  60. package/docs/components/tree.html +5 -4
  61. package/docs/index.html +22 -21
  62. package/docs/nav-1.inc.html +18 -12
  63. package/docs/nav.inc.html +20 -13
  64. package/docs/nav.inc.js +1 -1
  65. package/docs/src/components/Aside.js +326 -0
  66. package/docs/src/components/Dialog.js +1 -1
  67. package/docs/src/components/Dropdown.js +1 -1
  68. package/docs/src/components/Main.js +2 -2
  69. package/docs/src/components/Nav.js +27 -0
  70. package/docs/src/components/PhotoViewer.js +1 -1
  71. package/docs/src/components/ShadowComponent.js +1 -1
  72. package/docs/src/components/ThemeSwitcher.js +1 -0
  73. package/docs/src/components/Toast.js +1 -1
  74. package/docs/utils/context.html +4 -3
  75. package/docs/utils/cookie.html +4 -3
  76. package/docs/utils/debounce.html +4 -3
  77. package/docs/utils/drag.html +4 -3
  78. package/docs/utils/elevation.html +156 -0
  79. package/docs/utils/formatTimestamp.html +4 -3
  80. package/docs/utils/object.html +4 -3
  81. package/docs/utils/propConverters.html +4 -3
  82. package/docs/utils/string.html +4 -3
  83. package/docs/utils/theme.html +4 -3
  84. package/docs/utils/toTitleCase.html +4 -3
  85. package/docs/utils/type.html +4 -3
  86. package/docs/utils/wait.html +4 -3
  87. package/llm.txt +247 -0
  88. package/package.json +3 -4
  89. package/src/components/Aside.js +726 -0
  90. package/src/components/Dialog.js +1 -1
  91. package/src/components/Dropdown.js +1 -1
  92. package/src/components/Main.js +34 -30
  93. package/src/components/Nav.js +53 -0
  94. package/src/components/PhotoViewer.js +1 -1
  95. package/src/components/ShadowComponent.js +1 -1
  96. package/src/components/ThemeSwitcher.js +1 -0
  97. package/src/components/Toast.js +1 -1
  98. package/tests/bin/get_icon.node-test.js +26 -0
  99. package/tests/bin/highlight_code.node-test.js +108 -0
  100. package/tests/bin/list_icons.node-test.js +26 -0
  101. package/tests/components/Aside.browser-test.js +778 -0
  102. package/tests/components/Main.browser-test.js +115 -283
  103. package/dist/components/SideMenu.js +0 -97
  104. package/dist/components/SidePanel.js +0 -236
  105. package/docs/components/side-menu.html +0 -189
  106. package/docs/components/side-panel-basic.html +0 -44
  107. package/docs/components/side-panel-dual.html +0 -70
  108. package/docs/components/side-panel-menu.html +0 -50
  109. package/docs/components/side-panel-persistent.html +0 -90
  110. package/docs/components/side-panel-scroll.html +0 -176
  111. package/docs/components/side-panel.html +0 -245
  112. package/docs/src/components/SideMenu.js +0 -97
  113. package/docs/src/components/SidePanel.js +0 -236
  114. package/scripts/update-kempo-css.js +0 -53
  115. package/src/components/SideMenu.js +0 -178
  116. package/src/components/SidePanel.js +0 -513
  117. package/tests/components/SideMenu.browser-test.js +0 -667
  118. package/tests/components/SidePanel.browser-test.js +0 -520
  119. package/tools/highlight.js +0 -51
@@ -1,513 +0,0 @@
1
- import ShadowComponent from './ShadowComponent.js';
2
- import { html, css, nothing } from '../lit-all.min.js';
3
- import './Icon.js';
4
-
5
- /*
6
- SidePanel
7
- */
8
- class SidePanel extends ShadowComponent {
9
- static properties = {
10
- collapsed: { type: Boolean, reflect: true },
11
- side: { type: String, reflect: true },
12
- persistentId: { type: String, reflect: true, attribute: 'persistent-id' }
13
- };
14
-
15
- constructor() {
16
- super();
17
- this.collapsed = false;
18
- this.side = 'left';
19
- this.persistentId = null;
20
- this.isInitialLoad = true;
21
- }
22
-
23
- toggleClick = () => this.toggle();
24
-
25
- updated(changedProperties) {
26
- super.updated(changedProperties);
27
-
28
- if(changedProperties.has('persistentId') && this.persistentId && window?.localStorage) {
29
- const key = `side-panel-persistent-id-${this.persistentId}`;
30
- const value = window.localStorage.getItem(key);
31
- if(value !== null) {
32
- this.collapsed = value === 'true';
33
- this.isInitialLoad = false;
34
- }
35
- }
36
-
37
- if(changedProperties.has('collapsed')) {
38
- if(this.persistentId && window?.localStorage && !this.isInitialLoad) {
39
- const key = `side-panel-persistent-id-${this.persistentId}`;
40
- window.localStorage.setItem(key, this.collapsed.toString());
41
- }
42
- this.isInitialLoad = false;
43
-
44
- const eventName = this.collapsed ? 'collapse' : 'expand';
45
- this.dispatchEvent(new CustomEvent(eventName));
46
- this.dispatchEvent(new CustomEvent('change', { detail: eventName }));
47
-
48
- window.dispatchEvent(new CustomEvent('side-panel-change', {
49
- detail: {
50
- collapsed: this.collapsed,
51
- width: this.collapsed ? '3.5rem' : '16rem',
52
- side: this.side
53
- }
54
- }));
55
- }
56
- }
57
-
58
- expand = () => this.collapsed = false;
59
- collapse = () => this.collapsed = true;
60
- toggle() {
61
- this.collapsed = !this.collapsed;
62
- this.dispatchEvent(new CustomEvent('toggle'));
63
- }
64
-
65
- render() {
66
- const getArrowDirection = () => {
67
- if(this.side === 'right'){
68
- return this.collapsed ? 'left' : 'right';
69
- }
70
- return this.collapsed ? 'right' : 'left';
71
- };
72
-
73
- return html`
74
- <div id="header">
75
- <slot name="logo"></slot>
76
- <button id="toggle" @click=${this.toggleClick} aria-label="${this.collapsed ? 'Expand panel' : 'Collapse panel'}">
77
- <k-icon name="arrow-line" direction="${getArrowDirection()}"></k-icon>
78
- </button>
79
- </div>
80
- <div id="content">
81
- <slot></slot>
82
- </div>
83
- `;
84
- }
85
-
86
- static styles = css`
87
- :host {
88
- --bg: var(--c_bg);
89
- --width-expanded: 16rem;
90
- --transition-duration: var(--animation_ms, 256ms);
91
- display: flex;
92
- flex-direction: column;
93
- position: fixed;
94
- top: 0;
95
- left: 0;
96
- height: 100vh;
97
- width: var(--width-expanded);
98
- transition: width var(--transition-duration);
99
- background: var(--bg);
100
- border-right: 1px solid var(--c_border);
101
- z-index: 99;
102
- }
103
- :host([collapsed]) {
104
- width: auto;
105
- }
106
- :host([side="right"]) {
107
- left: auto;
108
- right: 0;
109
- border-right: none;
110
- border-left: 1px solid var(--c_border);
111
- }
112
- #header {
113
- display: flex;
114
- align-items: center;
115
- justify-content: flex-end;
116
- gap: var(--spacer_h);
117
- padding: var(--spacer_h);
118
- border-bottom: 1px solid var(--c_border);
119
- flex-shrink: 0;
120
- }
121
- ::slotted([slot="logo"]) {
122
- margin-right: auto;
123
- flex: 1;
124
- min-width: 0;
125
- opacity: 1;
126
- transition: opacity var(--transition-duration);
127
- }
128
- :host([collapsed]) ::slotted([slot="logo"]) {
129
- display: none;
130
- }
131
- #toggle {
132
- flex-shrink: 0;
133
- width: 2rem;
134
- height: 2rem;
135
- border: none;
136
- background: transparent;
137
- color: var(--c_text);
138
- cursor: pointer;
139
- display: flex;
140
- align-items: center;
141
- justify-content: center;
142
- border-radius: var(--radius);
143
- }
144
- #toggle:hover {
145
- background: var(--c_bg_hover);
146
- }
147
- #content {
148
- flex: 1;
149
- min-height: 0;
150
- overflow-y: auto;
151
- overflow-x: hidden;
152
- display: flex;
153
- flex-direction: column;
154
- }
155
- :host([collapsed]) #content {
156
- align-items: flex-start;
157
- }
158
- :host(:not([collapsed])) #content {
159
- /* scrollbar-gutter: stable; */
160
- }
161
- `;
162
- }
163
-
164
- /*
165
- SidePanelItem
166
- */
167
- class SidePanelItem extends ShadowComponent {
168
- static properties = {
169
- icon: { type: String },
170
- href: { type: String },
171
- active: { type: Boolean, reflect: true },
172
- collapsed: { type: Boolean, reflect: true },
173
- 'no-expand': { type: Boolean, attribute: 'no-expand' },
174
- 'hide-when-collapsed': { type: Boolean, attribute: 'hide-when-collapsed' }
175
- };
176
-
177
- constructor() {
178
- super();
179
- this.icon = '';
180
- this.href = '#';
181
- this.active = false;
182
- this.collapsed = false;
183
- this['no-expand'] = false;
184
- this['hide-when-collapsed'] = false;
185
- }
186
-
187
- connectedCallback() {
188
- super.connectedCallback();
189
- this.panel = this.closest('k-side-panel');
190
- if(this.panel) {
191
- this.collapsed = this.panel.collapsed;
192
- this.panel.addEventListener('collapse', this.handleCollapse);
193
- this.panel.addEventListener('expand', this.handleExpand);
194
- }
195
- }
196
-
197
- disconnectedCallback() {
198
- super.disconnectedCallback();
199
- if(this.panel) {
200
- this.panel.removeEventListener('collapse', this.handleCollapse);
201
- this.panel.removeEventListener('expand', this.handleExpand);
202
- }
203
- }
204
-
205
- handleCollapse = () => {
206
- this.collapsed = true;
207
- this.requestUpdate();
208
- };
209
-
210
- handleExpand = () => {
211
- this.collapsed = false;
212
- this.requestUpdate();
213
- };
214
-
215
- handleClick = (e) => {
216
- if(this.collapsed && !this['no-expand'] && this.panel) {
217
- e.preventDefault();
218
- this.panel.expand();
219
- }
220
- };
221
-
222
- render() {
223
- return html`
224
- <a href="${this.href}" class="item ${this.active ? 'active bg-primary' : ''}" @click=${this.handleClick}>
225
- ${this.icon ? html`<k-icon name="${this.icon}"></k-icon>` : this.collapsed ? html`<k-icon name="dot"></k-icon>` : nothing}
226
- ${this.collapsed ? nothing : html`<span class="label"><slot></slot></span>`}
227
- </a>
228
- `;
229
- }
230
-
231
- static styles = css`
232
- :host {
233
- display: block;
234
- }
235
- :host([collapsed][hide-when-collapsed]) {
236
- display: none;
237
- }
238
- .item {
239
- display: flex;
240
- align-items: center;
241
- gap: var(--spacer_h);
242
- padding: var(--spacer_h);
243
- color: var(--c_text);
244
- text-decoration: none;
245
- border-radius: var(--radius);
246
- margin: 0 var(--spacer_h);
247
- transition: background var(--animation_ms), color var(--animation_ms);
248
- white-space: nowrap;
249
- }
250
- :host([collapsed]) .item {
251
- }
252
- .item:hover {
253
- background: var(--c_bg_hover);
254
- }
255
- .item.active {
256
- color: var(--tc_on_primary);
257
- }
258
- .item.active:hover {
259
- background: var(--c_primary);
260
- filter: brightness(1.1);
261
- }
262
- k-icon {
263
- flex-shrink: 0;
264
- }
265
- .label {
266
- min-width: 0;
267
- overflow: hidden;
268
- text-overflow: ellipsis;
269
- }
270
- `;
271
- }
272
-
273
- /*
274
- SidePanelLabel
275
- */
276
- class SidePanelLabel extends ShadowComponent {
277
- static properties = {
278
- collapsed: { type: Boolean, reflect: true }
279
- };
280
-
281
- constructor() {
282
- super();
283
- this.collapsed = false;
284
- }
285
-
286
- connectedCallback() {
287
- super.connectedCallback();
288
- this.panel = this.closest('k-side-panel');
289
- if(this.panel) {
290
- this.collapsed = this.panel.collapsed;
291
- this.panel.addEventListener('collapse', this.handleCollapse);
292
- this.panel.addEventListener('expand', this.handleExpand);
293
- }
294
- }
295
-
296
- disconnectedCallback() {
297
- super.disconnectedCallback();
298
- if(this.panel) {
299
- this.panel.removeEventListener('collapse', this.handleCollapse);
300
- this.panel.removeEventListener('expand', this.handleExpand);
301
- }
302
- }
303
-
304
- handleCollapse = () => {
305
- this.collapsed = true;
306
- this.requestUpdate();
307
- };
308
-
309
- handleExpand = () => {
310
- this.collapsed = false;
311
- this.requestUpdate();
312
- };
313
-
314
- render() {
315
- return this.collapsed
316
- ? html`<hr>`
317
- : html`<div class="label"><slot></slot></div>`;
318
- }
319
-
320
- static styles = css`
321
- :host {
322
- display: block;
323
- margin: var(--spacer_h) 0;
324
- }
325
- :host([collapsed]) {
326
- margin: 0 var(--spacer_h);
327
- align-self: stretch;
328
- }
329
- .label {
330
- padding: 0 var(--spacer);
331
- font-size: 0.75rem;
332
- font-weight: 600;
333
- text-transform: uppercase;
334
- color: var(--c_text_muted);
335
- letter-spacing: 0.05em;
336
- }
337
- hr {
338
- border: none;
339
- border-top: 1px solid var(--c_border);
340
- margin: var(--spacer_h) var(--spacer);
341
- }
342
- :host([collapsed]) hr {
343
- margin: var(--spacer_h) 0;
344
- }
345
- `;
346
- }
347
-
348
- /*
349
- SidePanelMenu
350
- */
351
- class SidePanelMenu extends ShadowComponent {
352
- static properties = {
353
- icon: { type: String },
354
- label: { type: String },
355
- open: { type: Boolean, reflect: true },
356
- collapsed: { type: Boolean, reflect: true },
357
- 'no-expand': { type: Boolean, attribute: 'no-expand' },
358
- 'hide-when-collapsed': { type: Boolean, attribute: 'hide-when-collapsed' }
359
- };
360
-
361
- constructor() {
362
- super();
363
- this.icon = '';
364
- this.label = '';
365
- this.open = false;
366
- this.collapsed = false;
367
- this['no-expand'] = false;
368
- this['hide-when-collapsed'] = false;
369
- }
370
-
371
- connectedCallback() {
372
- super.connectedCallback();
373
- this.panel = this.closest('k-side-panel');
374
- if(this.panel) {
375
- this.collapsed = this.panel.collapsed;
376
- this.panel.addEventListener('collapse', this.handleCollapse);
377
- this.panel.addEventListener('expand', this.handleExpand);
378
- }
379
- }
380
-
381
- disconnectedCallback() {
382
- super.disconnectedCallback();
383
- if(this.panel) {
384
- this.panel.removeEventListener('collapse', this.handleCollapse);
385
- this.panel.removeEventListener('expand', this.handleExpand);
386
- }
387
- }
388
-
389
- handleCollapse = () => {
390
- this.collapsed = true;
391
- this.open = false;
392
- this.requestUpdate();
393
- };
394
-
395
- handleExpand = () => {
396
- this.collapsed = false;
397
- this.requestUpdate();
398
- };
399
-
400
- toggleMenu = () => {
401
- if(this.collapsed && !this['no-expand'] && this.panel) {
402
- this.panel.expand();
403
- } else if(!this.collapsed) {
404
- this.open = !this.open;
405
- }
406
- };
407
-
408
- render() {
409
- return html`
410
- <div class="menu-container">
411
- <button class="no-btn menu-header ${this.open ? 'open' : ''}" @click=${this.toggleMenu}>
412
- ${this.icon ? html`<k-icon name="${this.icon}"></k-icon>` : this.collapsed ? html`<k-icon name="dot"></k-icon>` : nothing}
413
- ${this.collapsed ? nothing : html`<span class="label">${this.label}</span>`}
414
- ${!this.collapsed ? html`<k-icon class="chevron" name="chevron" direction="${this.open ? 'down' : 'right'}"></k-icon>` : nothing}
415
- </button>
416
- <div class="menu-content ${this.open && !this.collapsed ? 'open' : ''}">
417
- <slot></slot>
418
- </div>
419
- </div>
420
- `;
421
- }
422
-
423
- static styles = css`
424
- :host {
425
- display: block;
426
- }
427
- :host([collapsed][hide-when-collapsed]) {
428
- display: none;
429
- }
430
- .menu-container {
431
- margin: 0;
432
- }
433
- .menu-header {
434
- display: flex !important;
435
- align-items: center;
436
- gap: var(--spacer_h);
437
- padding-top: var(--spacer_h) !important;
438
- padding-bottom: var(--spacer_h) !important;
439
- padding-left: var(--spacer_h) !important;
440
- padding-right: var(--spacer_h) !important;
441
- color: var(--c_text);
442
- background: transparent;
443
- border: none;
444
- border-radius: var(--radius);
445
- margin: 0 var(--spacer_h);
446
- width: calc(100% - var(--spacer));
447
- cursor: pointer;
448
- text-align: left;
449
- white-space: nowrap;
450
- transition: background var(--animation_ms);
451
- }
452
- :host([collapsed]) .menu-header {
453
- width: auto;
454
- }
455
- .menu-header:hover {
456
- background: var(--c_bg_hover);
457
- }
458
- k-icon {
459
- flex-shrink: 0;
460
- }
461
- .label {
462
- flex: 1;
463
- min-width: 0;
464
- overflow: hidden;
465
- text-overflow: ellipsis;
466
- }
467
- .chevron {
468
- transition: transform var(--animation_ms);
469
- }
470
- .menu-content {
471
- max-height: 0;
472
- overflow: hidden;
473
- transition: max-height var(--animation_ms);
474
- padding-left: calc(var(--spacer_h) * 2);
475
- }
476
- :host([collapsed]) .menu-content {
477
- padding-left: 0;
478
- }
479
- .menu-content.open {
480
- max-height: 500px;
481
- }
482
- ::slotted(*) {
483
- margin: 0.25rem 0;
484
- }
485
- `;
486
- }
487
-
488
- /*
489
- SidePanelSpacer
490
- */
491
- class SidePanelSpacer extends ShadowComponent {
492
- render() {
493
- return html`<div class="spacer"></div>`;
494
- }
495
-
496
- static styles = css`
497
- :host {
498
- display: block;
499
- flex: 1;
500
- }
501
- .spacer {
502
- height: 100%;
503
- }
504
- `;
505
- }
506
-
507
- customElements.define('k-side-panel', SidePanel);
508
- customElements.define('k-side-panel-item', SidePanelItem);
509
- customElements.define('k-side-panel-label', SidePanelLabel);
510
- customElements.define('k-side-panel-menu', SidePanelMenu);
511
- customElements.define('k-side-panel-spacer', SidePanelSpacer);
512
-
513
- export default SidePanel;