kempo-ui 0.0.7 → 0.0.9

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 (60) hide show
  1. package/dist/src/components/Icon.js +1 -1
  2. package/dist/src/components/ShadowComponent.js +1 -1
  3. package/dist/src/components/Tree.js +37 -0
  4. package/docs/components/accordion.html +3 -9
  5. package/docs/components/card.html +3 -9
  6. package/docs/components/collapsible.html +3 -9
  7. package/docs/components/content-slider.html +4 -9
  8. package/docs/components/dialog.html +157 -72
  9. package/docs/components/focus-capture.html +3 -7
  10. package/docs/components/hybrid-component.html +3 -7
  11. package/docs/components/icon.html +3 -8
  12. package/docs/components/import.html +1 -6
  13. package/docs/components/init.js +7 -0
  14. package/docs/components/light-component.html +3 -7
  15. package/docs/components/persistant-collapsible.html +1 -8
  16. package/docs/components/photo-viewer.html +1 -8
  17. package/docs/components/resize.html +3 -9
  18. package/docs/components/shadow-component.html +3 -7
  19. package/docs/components/show-more.html +3 -9
  20. package/docs/components/side-menu.html +1 -6
  21. package/docs/components/sortable.html +3 -7
  22. package/docs/components/split.html +3 -7
  23. package/docs/components/table.html +3 -7
  24. package/docs/components/tableControls.html +3 -7
  25. package/docs/components/tableCustomFields.html +3 -7
  26. package/docs/components/tableFetchRecords.html +3 -7
  27. package/docs/components/tableFieldSortHide.html +3 -7
  28. package/docs/components/tablePagination.html +3 -7
  29. package/docs/components/tableRecordEditing.html +3 -7
  30. package/docs/components/tableRecordFiltering.html +3 -7
  31. package/docs/components/tableRecordHiding.html +3 -7
  32. package/docs/components/tableRecordSearching.html +3 -7
  33. package/docs/components/tableRecordSelection.html +3 -7
  34. package/docs/components/tableRowControls.html +3 -7
  35. package/docs/components/tableSorting.html +3 -7
  36. package/docs/components/tabs.html +3 -9
  37. package/docs/components/tags.html +3 -9
  38. package/docs/components/theme-switcher.html +3 -9
  39. package/docs/components/timestamp.html +3 -9
  40. package/docs/components/toast.html +80 -42
  41. package/docs/components/toggle.html +3 -9
  42. package/docs/components/tree.html +108 -21
  43. package/docs/index.html +10 -6
  44. package/docs/init.js +7 -0
  45. package/docs/src/components/Icon.js +1 -1
  46. package/docs/src/components/ShadowComponent.js +1 -1
  47. package/docs/src/components/Tree.js +37 -0
  48. package/docs/utils/debounce.html +1 -6
  49. package/docs/utils/drag.html +1 -6
  50. package/docs/utils/formatTimestamp.html +1 -6
  51. package/docs/utils/init.js +7 -0
  52. package/docs/utils/propConverters.html +1 -6
  53. package/docs/utils/toTitleCase.html +1 -6
  54. package/docs/utils/watchWindowSize.html +1 -6
  55. package/package.json +1 -1
  56. package/scripts/build.js +12 -2
  57. package/src/components/Card.js +2 -5
  58. package/src/components/Dialog.js +48 -34
  59. package/src/components/Icon.js +25 -18
  60. package/src/components/Tree.js +64 -72
@@ -0,0 +1,37 @@
1
+ import ShadowComponent from"./ShadowComponent.js";import{html,css,render}from"../lit-all.min.js";import{boolExists}from"../utils/propConverters.js";import"./Icon.js";export default class Tree extends ShadowComponent{static properties={data:{type:Object},depth:{type:Number,reflect:!0},editable:{type:Boolean,converter:boolExists,attribute:"editable",reflect:!0}};constructor(){super(),this.data=null,this.depth=0,this.editable=!1}render(){return this.data?"object"==typeof this.data&&null!==this.data?html`
2
+ <div class="tree-root">
3
+ ${(Array.isArray(this.data)?this.data.map((e,t)=>[t,e]):Object.entries(this.data)).map(([e,t])=>Tree.renderValue(t,e,1,this.depth))}
4
+ </div>
5
+ `:html`
6
+ <div class="tree-root">
7
+ ${Tree.renderValue(this.data,null,0,this.depth)}
8
+ </div>
9
+ `:html`<slot></slot>`}static leafs=[];static addLeaf=(...e)=>{e.forEach(e=>Tree.leafs.unshift(e))};static renderValue(e,t=null,s=0,r=0){const a=Tree.leafs.find(t=>t.detect(e));if(a){const s=document.createElement("span");if(s.className="d-b",null!==t){const e=document.createElement("span");e.className="number"==typeof t?"tc-muted":"",e.textContent=`${t}: `,s.appendChild(e)}const r=new a(e).render();if(r instanceof Node)s.appendChild(r);else{const e=document.createElement("span");render(r,e),s.appendChild(e)}return s}if("object"==typeof e&&null!==e){const a=new TreeBranch;return a.value=e,a.key=t,a.currentDepth=s,a.maxDepth=r,a}return html`<span class="d-b primitive">${null!==t?html`<span class="${"number"==typeof t?"tc-muted":""}">${t}: </span>`:""}${e}</span>`}}window.customElements.define("k-tree",Tree);export class TreeBranch extends ShadowComponent{static properties={value:{type:Object},key:{type:String},currentDepth:{type:Number},maxDepth:{type:Number},opened:{type:Boolean,converter:boolExists,reflect:!0}};constructor(){super(),this.value=null,this.key=null,this.currentDepth=0,this.maxDepth=0,this.opened=!1}connectedCallback(){super.connectedCallback(),this.currentDepth<=this.maxDepth&&(this.opened=!0)}get tree(){return this.closest("k-tree")}toggle=()=>{this.opened=!this.opened};render(){const e=null!==this.key?`${this.key}: `:"",t=Array.isArray(this.value)?"Array":"Object";return html`
10
+ <div>
11
+ <div class="branch-label" @click=${this.toggle}>
12
+ <k-icon name="chevron-right" class="toggle-icon ${this.opened?"opened":""}"></k-icon>
13
+ ${e}${t}
14
+ </div>
15
+ ${this.opened?html`
16
+ <div class="pl">
17
+ ${this.value?(Array.isArray(this.value)?this.value.map((e,t)=>[t,e]):Object.entries(this.value)).map(([e,t])=>Tree.renderValue(t,e,this.currentDepth+1,this.maxDepth)):""}
18
+ </div>
19
+ `:""}
20
+ </div>
21
+ `}static styles=css`
22
+ :host{
23
+ display: block;
24
+ }
25
+ .branch-label{
26
+ cursor: pointer;
27
+ }
28
+ .branch-label:hover{
29
+ background-color: var(--c_bg__alt, #f5f5f5);
30
+ }
31
+ .toggle-icon{
32
+ transition: transform var(--animation_ms, 200ms);
33
+ }
34
+ .toggle-icon.opened{
35
+ transform: rotate(90deg);
36
+ }
37
+ `}window.customElements.define("k-tree-branch",TreeBranch);export class TreeLeaf{constructor(e=null){this.value=e}render(){return html`${this.value}`}static detect=()=>!1}export class StringLeaf extends TreeLeaf{render(){return html`<span class="tc-success">"${this.value}"</span>`}static detect=e=>"string"==typeof e}export class NumberLeaf extends TreeLeaf{render(){return html`<span class="tc-primary">${this.value}</span>`}static detect=e=>"number"==typeof e}export class BooleanLeaf extends TreeLeaf{render(){return html`<span class="${this.value?"tc-success":"tc-danger"}">${this.value}</span>`}static detect=e=>"boolean"==typeof e}export class NullLeaf extends TreeLeaf{render(){return html`<span class="tc-muted">null</span>`}static detect=e=>null===e}export class UndefinedLeaf extends TreeLeaf{render(){return html`<span class="tc-muted">undefined</span>`}static detect=e=>void 0===e}Tree.addLeaf(UndefinedLeaf,NullLeaf,BooleanLeaf,NumberLeaf,StringLeaf);
@@ -8,12 +8,7 @@
8
8
  <link rel="stylesheet" href="../kempo.min.css" />
9
9
  <link rel="stylesheet" href="../src/kempo-hljs.css" />
10
10
  <link rel="stylesheet" href="../styles.css" />
11
- <script type="module">
12
- import Import from '../src/components/Import.js';
13
- import Icon from '../src/components/Icon.js';
14
- Import.replacements.root = '../';
15
- Icon.pathToIcons = ['../icons'];
16
- </script>
11
+ <script type="module" src="./init.js"></script>
17
12
  </head>
18
13
  <body>
19
14
  <k-import src="../nav.inc.html"></k-import>
@@ -8,12 +8,7 @@
8
8
  <link rel="stylesheet" href="../kempo.min.css" />
9
9
  <link rel="stylesheet" href="../src/kempo-hljs.css" />
10
10
  <link rel="stylesheet" href="../styles.css" />
11
- <script type="module">
12
- import Import from '../src/components/Import.js';
13
- import Icon from '../src/components/Icon.js';
14
- Import.replacements.root = '../';
15
- Icon.pathToIcons = ['../icons'];
16
- </script>
11
+ <script type="module" src="./init.js"></script>
17
12
  </head>
18
13
  <body>
19
14
  <k-import src="../nav.inc.html"></k-import>
@@ -8,12 +8,7 @@
8
8
  <link rel="stylesheet" href="../kempo.min.css" />
9
9
  <link rel="stylesheet" href="../src/kempo-hljs.css" />
10
10
  <link rel="stylesheet" href="../styles.css" />
11
- <script type="module">
12
- import Import from '../src/components/Import.js';
13
- import Icon from '../src/components/Icon.js';
14
- Import.replacements.root = '../';
15
- Icon.pathToIcons = ['../icons'];
16
- </script>
11
+ <script type="module" src="./init.js"></script>
17
12
  </head>
18
13
  <body>
19
14
  <k-import src="../nav.inc.html"></k-import>
@@ -0,0 +1,7 @@
1
+ import Import from '../src/components/Import.js';
2
+ import Icon from '../src/components/Icon.js';
3
+ import ShadowComponent from '../src/components/ShadowComponent.js';
4
+
5
+ Import.replacements.root = '../';
6
+ Icon.pathToIcons = ['../icons'];
7
+ ShadowComponent.stylesheetPath = '../kempo.min.css';
@@ -8,12 +8,7 @@
8
8
  <link rel="stylesheet" href="../kempo.min.css" />
9
9
  <link rel="stylesheet" href="../src/kempo-hljs.css" />
10
10
  <link rel="stylesheet" href="../styles.css" />
11
- <script type="module">
12
- import Import from '../src/components/Import.js';
13
- import Icon from '../src/components/Icon.js';
14
- Import.replacements.root = '../';
15
- Icon.pathToIcons = ['../icons'];
16
- </script>
11
+ <script type="module" src="./init.js"></script>
17
12
  </head>
18
13
  <body>
19
14
  <k-import src="../nav.inc.html"></k-import>
@@ -8,12 +8,7 @@
8
8
  <link rel="stylesheet" href="../kempo.min.css" />
9
9
  <link rel="stylesheet" href="../src/kempo-hljs.css" />
10
10
  <link rel="stylesheet" href="../styles.css" />
11
- <script type="module">
12
- import Import from '../src/components/Import.js';
13
- import Icon from '../src/components/Icon.js';
14
- Import.replacements.root = '../';
15
- Icon.pathToIcons = ['../icons'];
16
- </script>
11
+ <script type="module" src="./init.js"></script>
17
12
  </head>
18
13
  <body>
19
14
  <k-import src="../nav.inc.html"></k-import>
@@ -8,12 +8,7 @@
8
8
  <link rel="stylesheet" href="../kempo.min.css" />
9
9
  <link rel="stylesheet" href="../src/kempo-hljs.css" />
10
10
  <link rel="stylesheet" href="../styles.css" />
11
- <script type="module">
12
- import Import from '../src/components/Import.js';
13
- import Icon from '../src/components/Icon.js';
14
- Import.replacements.root = '../';
15
- Icon.pathToIcons = ['../icons'];
16
- </script>
11
+ <script type="module" src="./init.js"></script>
17
12
  </head>
18
13
  <body>
19
14
  <k-import src="../nav.inc.html"></k-import>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kempo-ui",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "description": "A Lit based web-component library",
6
6
  "main": "index.js",
package/scripts/build.js CHANGED
@@ -48,13 +48,23 @@ process.stdout.write(`0/${allJSFiles.length} = 0%`);
48
48
  const processedJS = {};
49
49
  await Promise.all(allJSFiles.map(async jsFile => {
50
50
  const filename = path.basename(jsFile);
51
+ let code = jsCode[jsFile];
52
+
51
53
  if (filename.endsWith('.min.js')) {
52
54
  // Already minified, just copy
53
- processedJS[jsFile] = jsCode[jsFile];
55
+ processedJS[jsFile] = code;
54
56
  } else {
55
57
  // Minify the file
56
- processedJS[jsFile] = (await minify(jsCode[jsFile])).code;
58
+ code = (await minify(code)).code;
57
59
  }
60
+
61
+ // Convert absolute paths to relative paths for GitHub Pages compatibility
62
+ // This handles paths in ShadowComponent and Icon
63
+ code = code.replace(/stylesheetPath\s*=\s*"\/kempo\.min\.css"/g, 'stylesheetPath="./kempo.min.css"');
64
+ code = code.replace(/pathToIcons\s*=\s*\["\/icons"\]/g, 'pathToIcons=["./icons"]');
65
+
66
+ processedJS[jsFile] = code;
67
+
58
68
  process.stdout.write("\r");
59
69
  complete++;
60
70
  process.stdout.write(`${complete}/${allJSFiles.length} = ${Math.round((complete/allJSFiles.length)*100)}%`);
@@ -11,7 +11,7 @@ export default class Card extends ShadowComponent {
11
11
 
12
12
  constructor() {
13
13
  super();
14
- this.label = '';
14
+ this.label = null;
15
15
  }
16
16
 
17
17
  /*
@@ -38,12 +38,9 @@ export default class Card extends ShadowComponent {
38
38
  border-radius: var(--radius);
39
39
  padding: var(--spacer_h);
40
40
  }
41
- :host([label]) {
42
- padding-top: calc(1.5 * var(--spacer));
43
- margin-top: var(--spacer);
44
- }
45
41
  :host([label]) #card {
46
42
  padding-top: calc(1.5 * var(--spacer));
43
+ margin-top: var(--spacer);
47
44
  }
48
45
  :host(:not([label])) #label {
49
46
  display: none;
@@ -227,13 +227,13 @@ export default class Dialog extends ShadowComponent {
227
227
  return html`
228
228
  <button id="overlay" aria-label="Close the Dialog" @click=${this.handleClick}></button>
229
229
  <div id="wrapper">
230
- <div
231
- id="dialog"
232
- role="dialog"
233
- aria-modal="true"
234
- aria-labelledby="title"
235
- >
236
- <k-focus-capture>
230
+ <k-focus-capture>
231
+ <div
232
+ id="dialog"
233
+ role="dialog"
234
+ aria-modal="true"
235
+ aria-labelledby="title"
236
+ >
237
237
  <div
238
238
  id="header"
239
239
  class="${this.hasTitle() ? 'has-title' : ''}"
@@ -264,8 +264,8 @@ export default class Dialog extends ShadowComponent {
264
264
  ` : ''}
265
265
  </div>
266
266
  ` : ''}
267
- </k-focus-capture>
268
- </div>
267
+ </div>
268
+ </k-focus-capture>
269
269
  </div>
270
270
  `;
271
271
  }
@@ -280,7 +280,9 @@ export default class Dialog extends ShadowComponent {
280
280
 
281
281
  const {
282
282
  removeOnClose = true,
283
- closeCallback = () => {}
283
+ closeCallback = () => {},
284
+ title = '',
285
+ titleClasses = 'pyh px m0'
284
286
  } = options;
285
287
 
286
288
  const dialog = new Dialog();
@@ -297,11 +299,33 @@ export default class Dialog extends ShadowComponent {
297
299
  }
298
300
  });
299
301
 
302
+ // Set title if provided
303
+ if(title) {
304
+ const titleElement = document.createElement('h5');
305
+ titleElement.slot = 'title';
306
+ titleElement.className = titleClasses;
307
+ if(title instanceof HTMLElement) {
308
+ titleElement.appendChild(title);
309
+ } else {
310
+ titleElement.innerHTML = title;
311
+ }
312
+ dialog.appendChild(titleElement);
313
+ }
314
+
300
315
  // Set content
301
316
  if(contents instanceof HTMLElement || contents instanceof DocumentFragment) {
302
317
  dialog.appendChild(contents);
303
318
  } else if(contents) {
304
- dialog.innerHTML = contents;
319
+ // Check if content is plain text (no HTML tags)
320
+ const hasHtmlTags = /<[^>]+>/.test(contents);
321
+ if(hasHtmlTags) {
322
+ dialog.innerHTML += contents;
323
+ } else {
324
+ const p = document.createElement('p');
325
+ p.className = 'p';
326
+ p.textContent = contents;
327
+ dialog.appendChild(p);
328
+ }
305
329
  }
306
330
 
307
331
  // Set CSS custom properties for dimensions
@@ -319,11 +343,8 @@ export default class Dialog extends ShadowComponent {
319
343
  }
320
344
 
321
345
  static confirm(text, responseCallback, options = {}) {
322
- const title = options.title || 'Confirm';
323
- return Dialog.create(`
324
- <h5 slot="title" class="pyh px m0">${title}</h5>
325
- <p class="p">${text}</p>
326
- `, {
346
+ return Dialog.create(text, {
347
+ title: options.title || 'Confirm',
327
348
  closeBtn: false,
328
349
  overlayClose: false,
329
350
  confirmText: 'Yes',
@@ -336,36 +357,29 @@ export default class Dialog extends ShadowComponent {
336
357
  });
337
358
  }
338
359
 
339
- static alert(text, responseCallback, options = {}) {
340
- const title = options.title || 'Alert';
341
- return Dialog.create(`
342
- <h5 slot="title" class="pyh px m0">${title}</h5>
343
- <p class="p">${text}</p>
344
- `, {
360
+ static alert(text, responseCallback = () => {}, options = {}) {
361
+ return Dialog.create(text, {
362
+ title: options.title || 'Alert',
345
363
  closeCallback: responseCallback,
346
364
  cancelText: 'Ok',
347
365
  ...options
348
366
  });
349
367
  }
350
368
 
351
- static error(text, responseCallback, options = {}) {
352
- const title = options.title || 'Error';
353
- return Dialog.create(`
354
- <h5 slot="title" class="pyh px m0 tc-danger">${title}</h5>
355
- <p class="p">${text}</p>
356
- `, {
369
+ static error(text, responseCallback = () => {}, options = {}) {
370
+ return Dialog.create(text, {
371
+ title: options.title || 'Error',
372
+ titleClasses: 'pyh px m0 tc-danger',
357
373
  closeCallback: responseCallback,
358
374
  cancelText: 'Ok',
359
375
  ...options
360
376
  });
361
377
  }
362
378
 
363
- static success(text, responseCallback, options = {}) {
364
- const title = options.title || 'Success';
365
- return Dialog.create(`
366
- <h5 slot="title" class="pyh px m0 tc-success">${title}</h5>
367
- <p class="p">${text}</p>
368
- `, {
379
+ static success(text, responseCallback = () => {}, options = {}) {
380
+ return Dialog.create(text, {
381
+ title: options.title || 'Success',
382
+ titleClasses: 'pyh px m0 tc-success',
369
383
  closeCallback: responseCallback,
370
384
  cancelText: 'Ok',
371
385
  ...options
@@ -69,10 +69,6 @@ export default class Icon extends ShadowComponent {
69
69
  if (changedProperties.has('src') || changedProperties.has('name')) {
70
70
  this.loadIcon();
71
71
  }
72
-
73
- if (changedProperties.has('iconContent')) {
74
- this.fixSVG();
75
- }
76
72
  }
77
73
 
78
74
  /*
@@ -88,30 +84,41 @@ export default class Icon extends ShadowComponent {
88
84
  }
89
85
 
90
86
  if (svg) {
91
- this.iconContent = svg;
87
+ this.iconContent = this.fixSVG(svg);
92
88
  } else {
93
89
  // Check for slotted fallback content first
94
90
  const slottedContent = this.innerHTML.trim();
95
91
  if (slottedContent) {
96
- this.iconContent = slottedContent;
92
+ this.iconContent = this.fixSVG(slottedContent);
97
93
  } else {
98
94
  this.iconContent = Icon.fallback;
99
95
  }
100
96
  }
101
97
  }
102
98
 
103
- fixSVG() {
104
- // Use setTimeout to ensure DOM is updated
105
- setTimeout(() => {
106
- const $svg = this.querySelector('svg');
107
- if ($svg) {
108
- $svg.removeAttribute('width');
109
- $svg.removeAttribute('height');
110
- $svg.querySelectorAll('path, rect, circle').forEach($path => {
111
- $path.setAttribute('fill', 'currentColor');
112
- });
113
- }
114
- }, 0);
99
+ fixSVG(svgString) {
100
+ if(!svgString) return svgString;
101
+
102
+ // Parse the SVG string and fix attributes
103
+ const parser = new DOMParser();
104
+ const doc = parser.parseFromString(svgString, 'image/svg+xml');
105
+ const $svg = doc.querySelector('svg');
106
+
107
+ if($svg) {
108
+ // Remove width and height attributes
109
+ $svg.removeAttribute('width');
110
+ $svg.removeAttribute('height');
111
+
112
+ // Set fill to currentColor on all paths, rects, and circles
113
+ $svg.querySelectorAll('path, rect, circle').forEach($el => {
114
+ $el.setAttribute('fill', 'currentColor');
115
+ });
116
+
117
+ // Return the fixed SVG as a string
118
+ return new XMLSerializer().serializeToString($svg);
119
+ }
120
+
121
+ return svgString;
115
122
  }
116
123
 
117
124
  /*