kempo-ui 0.0.2 → 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 (278) hide show
  1. package/.github/copilot-instructions.md +149 -149
  2. package/.github/workflows/publish-major.yml +39 -0
  3. package/.github/workflows/publish-minor.yml +39 -0
  4. package/.github/workflows/{publish-npm.yml → publish-patch.yml} +44 -44
  5. package/.vscode/settings.json +2 -0
  6. package/CONTRIBUTING.md +149 -149
  7. package/README.md +0 -0
  8. package/dist/kempo-hljs.css +1 -0
  9. package/dist/kempo-vars.css +0 -0
  10. package/dist/src/components/Accordion.js +36 -0
  11. package/dist/src/components/Card.js +37 -0
  12. package/dist/src/components/Collapsible.js +41 -0
  13. package/dist/src/components/ContentSlider.js +44 -0
  14. package/dist/src/components/Dialog.js +113 -0
  15. package/dist/src/components/FocusCapture.js +7 -0
  16. package/dist/src/components/Icon.js +10 -0
  17. package/dist/src/components/Import.js +1 -0
  18. package/dist/src/components/PersistantCollapsible.js +1 -0
  19. package/dist/src/components/PhotoViewer.js +135 -0
  20. package/dist/src/components/Resize.js +96 -0
  21. package/dist/src/components/ShadowComponent.js +1 -0
  22. package/dist/src/components/ShowMore.js +42 -0
  23. package/dist/src/components/SideMenu.js +97 -0
  24. package/dist/src/components/Split.js +84 -0
  25. package/dist/src/components/Tabs.js +155 -0
  26. package/dist/src/components/Tags.js +69 -0
  27. package/dist/src/components/ThemeSwitcher.js +23 -0
  28. package/dist/src/components/Timestamp.js +1 -0
  29. package/dist/src/lit-all.min.js +120 -0
  30. package/dist/src/utils/debounce.js +1 -0
  31. package/dist/src/utils/drag.js +1 -0
  32. package/dist/src/utils/formatTimestamp.js +1 -0
  33. package/dist/src/utils/propConverters.js +1 -0
  34. package/dist/src/utils/watchWindowSize.js +1 -0
  35. package/docs/components/accordion.html +166 -0
  36. package/docs/components/card.html +92 -0
  37. package/docs/components/collapsible.html +198 -0
  38. package/docs/components/content-slider.html +223 -0
  39. package/docs/components/dialog.html +251 -0
  40. package/docs/components/focus-capture.html +67 -0
  41. package/docs/components/icon.html +158 -0
  42. package/docs/components/import.html +73 -0
  43. package/docs/components/persistant-collapsible.html +123 -0
  44. package/docs/components/photo-viewer.html +226 -0
  45. package/docs/components/resize.html +178 -0
  46. package/docs/components/show-more.html +129 -0
  47. package/docs/components/side-menu.html +159 -0
  48. package/docs/components/split.html +147 -0
  49. package/docs/components/table.html +312 -0
  50. package/docs/components/tableControls.html +77 -0
  51. package/docs/components/tableCustomFields.html +113 -0
  52. package/docs/components/tableFetchRecords.html +114 -0
  53. package/docs/components/tableFieldSortHide.html +75 -0
  54. package/docs/components/tablePagination.html +100 -0
  55. package/docs/components/tableRecordEditing.html +144 -0
  56. package/docs/components/tableRecordFiltering.html +88 -0
  57. package/docs/components/tableRecordHiding.html +80 -0
  58. package/docs/components/tableRecordSearching.html +75 -0
  59. package/docs/components/tableRecordSelection.html +75 -0
  60. package/docs/components/tableRowControls.html +78 -0
  61. package/docs/components/tableSorting.html +73 -0
  62. package/docs/components/tabs.html +180 -0
  63. package/docs/components/tags.html +110 -0
  64. package/docs/components/theme-switcher.html +126 -0
  65. package/docs/components/timestamp.html +82 -0
  66. package/docs/components/toast.html +319 -0
  67. package/docs/components/toggle.html +156 -0
  68. package/docs/dev.config.json +20 -0
  69. package/docs/icons/add.svg +1 -0
  70. package/docs/icons/arrow-back.svg +1 -0
  71. package/docs/icons/arrow-down-double.svg +1 -0
  72. package/docs/icons/arrow-down.svg +1 -0
  73. package/docs/icons/arrow-forward.svg +1 -0
  74. package/docs/icons/arrow-up-double.svg +1 -0
  75. package/docs/icons/arrow-up.svg +1 -0
  76. package/docs/icons/cards.svg +1 -0
  77. package/docs/icons/check.svg +1 -0
  78. package/docs/icons/chevron-left.svg +1 -0
  79. package/docs/icons/chevron-right.svg +1 -0
  80. package/docs/icons/close.svg +2 -0
  81. package/docs/icons/compare.svg +1 -0
  82. package/docs/icons/delete.svg +1 -0
  83. package/docs/icons/drag-handle.svg +1 -0
  84. package/docs/icons/drawing2.svg +124 -0
  85. package/docs/icons/edit.svg +1 -0
  86. package/docs/icons/error.svg +1 -0
  87. package/docs/icons/export-file.svg +1 -0
  88. package/docs/icons/file-text.svg +1 -0
  89. package/docs/icons/file.svg +1 -0
  90. package/docs/icons/filter-off.svg +1 -0
  91. package/docs/icons/filter.svg +1 -0
  92. package/docs/icons/first.svg +1 -0
  93. package/docs/icons/folder-clear.svg +1 -0
  94. package/docs/icons/folder-create.svg +1 -0
  95. package/docs/icons/folder-open.svg +1 -0
  96. package/docs/icons/folder.svg +1 -0
  97. package/docs/icons/hide.svg +1 -0
  98. package/docs/icons/image.svg +1 -0
  99. package/docs/icons/label-add.svg +1 -0
  100. package/docs/icons/label.svg +1 -0
  101. package/docs/icons/last.svg +1 -0
  102. package/docs/icons/menu.svg +1 -0
  103. package/docs/icons/mode-auto.svg +1 -0
  104. package/docs/icons/mode-dark.svg +1 -0
  105. package/docs/icons/mode-light.svg +1 -0
  106. package/docs/icons/open-in-browser.svg +1 -0
  107. package/docs/icons/pause.svg +1 -0
  108. package/docs/icons/play.svg +1 -0
  109. package/docs/icons/refresh.svg +1 -0
  110. package/docs/icons/remove.svg +1 -0
  111. package/docs/icons/save.svg +1 -0
  112. package/docs/icons/search.svg +1 -0
  113. package/docs/icons/settings.svg +1 -0
  114. package/docs/icons/show.svg +1 -0
  115. package/docs/icons/storage.svg +1 -0
  116. package/docs/icons/table-visibility.svg +1 -0
  117. package/docs/icons/tag.svg +1 -0
  118. package/docs/icons/tools.svg +1 -0
  119. package/docs/icons/trash-x.svg +1 -0
  120. package/docs/icons/warning.svg +1 -0
  121. package/docs/index.html +28 -21
  122. package/docs/kempo-hljs.css +1 -0
  123. package/docs/media/civic.jpg +0 -0
  124. package/docs/media/corvette.jpg +0 -0
  125. package/docs/media/evo.jpg +0 -0
  126. package/docs/media/gtr.jpg +0 -0
  127. package/docs/media/nsx.jpg +0 -0
  128. package/docs/nav.inc.html +67 -0
  129. package/docs/nav.inc.js +4 -0
  130. package/{config/production.json → docs/prod.config.json} +20 -16
  131. package/docs/src/components/Accordion.js +36 -0
  132. package/docs/src/components/Card.js +37 -0
  133. package/docs/src/components/Collapsible.js +41 -0
  134. package/docs/src/components/ContentSlider.js +44 -0
  135. package/docs/src/components/Dialog.js +113 -0
  136. package/docs/src/components/FocusCapture.js +7 -0
  137. package/docs/src/components/HybridComponent.js +1 -0
  138. package/docs/src/components/Icon.js +10 -0
  139. package/docs/src/components/Import.js +1 -0
  140. package/docs/src/components/LightComponent.js +1 -0
  141. package/docs/src/components/PersistantCollapsible.js +1 -0
  142. package/docs/src/components/PhotoViewer.js +135 -0
  143. package/docs/src/components/Resize.js +96 -0
  144. package/docs/src/components/ShadowComponent.js +1 -0
  145. package/docs/src/components/ShowMore.js +42 -0
  146. package/docs/src/components/SideMenu.js +97 -0
  147. package/docs/src/components/Split.js +84 -0
  148. package/docs/src/components/Tabs.js +155 -0
  149. package/docs/src/components/Tags.js +69 -0
  150. package/docs/src/components/ThemeSwitcher.js +23 -0
  151. package/docs/src/components/Timestamp.js +1 -0
  152. package/docs/src/lit-all.min.js +120 -0
  153. package/docs/src/utils/debounce.js +1 -0
  154. package/docs/src/utils/drag.js +1 -0
  155. package/docs/src/utils/formatTimestamp.js +1 -0
  156. package/docs/src/utils/propConverters.js +1 -0
  157. package/docs/src/utils/watchWindowSize.js +1 -0
  158. package/docs/styles.css +6 -0
  159. package/docs/utils/debounce.html +78 -0
  160. package/docs/utils/drag.html +104 -0
  161. package/docs/utils/formatTimestamp.html +114 -0
  162. package/docs/utils/propConverters.html +132 -0
  163. package/docs/utils/watchWindowSize.html +166 -0
  164. package/icons/add.svg +1 -0
  165. package/icons/arrow-back.svg +1 -0
  166. package/icons/arrow-down-double.svg +1 -0
  167. package/icons/arrow-down.svg +1 -0
  168. package/icons/arrow-forward.svg +1 -0
  169. package/icons/arrow-up-double.svg +1 -0
  170. package/icons/arrow-up.svg +1 -0
  171. package/icons/cards.svg +1 -0
  172. package/icons/check.svg +1 -0
  173. package/icons/chevron-left.svg +1 -0
  174. package/icons/chevron-right.svg +1 -0
  175. package/icons/close.svg +2 -0
  176. package/icons/compare.svg +1 -0
  177. package/icons/delete.svg +1 -0
  178. package/icons/drag-handle.svg +1 -0
  179. package/icons/drawing2.svg +124 -0
  180. package/icons/edit.svg +1 -0
  181. package/icons/error.svg +1 -0
  182. package/icons/export-file.svg +1 -0
  183. package/icons/file-text.svg +1 -0
  184. package/icons/file.svg +1 -0
  185. package/icons/filter-off.svg +1 -0
  186. package/icons/filter.svg +1 -0
  187. package/icons/first.svg +1 -0
  188. package/icons/folder-clear.svg +1 -0
  189. package/icons/folder-create.svg +1 -0
  190. package/icons/folder-open.svg +1 -0
  191. package/icons/folder.svg +1 -0
  192. package/icons/hide.svg +1 -0
  193. package/icons/image.svg +1 -0
  194. package/icons/label-add.svg +1 -0
  195. package/icons/label.svg +1 -0
  196. package/icons/last.svg +1 -0
  197. package/icons/menu.svg +1 -0
  198. package/icons/mode-auto.svg +1 -0
  199. package/icons/mode-dark.svg +1 -0
  200. package/icons/mode-light.svg +1 -0
  201. package/icons/open-in-browser.svg +1 -0
  202. package/icons/pause.svg +1 -0
  203. package/icons/play.svg +1 -0
  204. package/icons/refresh.svg +1 -0
  205. package/icons/remove.svg +1 -0
  206. package/icons/save.svg +1 -0
  207. package/icons/search.svg +1 -0
  208. package/icons/settings.svg +1 -0
  209. package/icons/show.svg +1 -0
  210. package/icons/storage.svg +1 -0
  211. package/icons/table-visibility.svg +1 -0
  212. package/icons/tag.svg +1 -0
  213. package/icons/tools.svg +1 -0
  214. package/icons/trash-x.svg +1 -0
  215. package/icons/warning.svg +1 -0
  216. package/package.json +2 -2
  217. package/scripts/build.js +109 -138
  218. package/scripts/docs.js +62 -60
  219. package/src/components/Accordion.js +229 -0
  220. package/src/components/Card.js +66 -0
  221. package/src/components/Collapsible.js +109 -0
  222. package/src/components/ContentSlider.js +205 -0
  223. package/src/components/Dialog.js +368 -0
  224. package/src/components/FocusCapture.js +23 -0
  225. package/src/components/HybridComponent.js +40 -40
  226. package/src/components/Icon.js +155 -0
  227. package/src/components/Import.js +104 -0
  228. package/src/components/LightComponent.js +32 -32
  229. package/src/components/PersistantCollapsible.js +69 -0
  230. package/src/components/PhotoViewer.js +368 -0
  231. package/src/components/Resize.js +210 -0
  232. package/src/components/ShadowComponent.js +32 -17
  233. package/src/components/ShowMore.js +109 -0
  234. package/src/components/SideMenu.js +167 -0
  235. package/src/components/Sortable.js +193 -0
  236. package/src/components/Split.js +192 -0
  237. package/src/components/Table.js +1202 -0
  238. package/src/components/Tabs.js +428 -0
  239. package/src/components/Tags.js +253 -0
  240. package/src/components/ThemeSwitcher.js +108 -0
  241. package/src/components/Timestamp.js +31 -0
  242. package/src/components/Toast.js +454 -0
  243. package/src/components/Toggle.js +173 -0
  244. package/src/components/tableControls/DeleteRecord.js +29 -0
  245. package/src/components/tableControls/Edit.js +88 -0
  246. package/src/components/tableControls/ExportCSV.js +71 -0
  247. package/src/components/tableControls/ExportJson.js +55 -0
  248. package/src/components/tableControls/FieldSortHide.js +76 -0
  249. package/src/components/tableControls/Filters.js +114 -0
  250. package/src/components/tableControls/FirstPage.js +65 -0
  251. package/src/components/tableControls/HiddenCount.js +45 -0
  252. package/src/components/tableControls/Hide.js +34 -0
  253. package/src/components/tableControls/LastPage.js +65 -0
  254. package/src/components/tableControls/NextPage.js +65 -0
  255. package/src/components/tableControls/PageSelect.js +109 -0
  256. package/src/components/tableControls/PageSize.js +68 -0
  257. package/src/components/tableControls/PrevPage.js +65 -0
  258. package/src/components/tableControls/Search.js +58 -0
  259. package/src/components/tableControls/ShowAll.js +34 -0
  260. package/src/components/tableControls/TableControl.js +105 -0
  261. package/src/kempo-hljs.css +146 -0
  262. package/src/utils/debounce.js +9 -0
  263. package/src/utils/drag.js +80 -0
  264. package/src/utils/formatTimestamp.js +27 -0
  265. package/src/utils/propConverters.js +11 -0
  266. package/src/utils/toTitleCase.js +9 -0
  267. package/src/utils/watchWindowSize.js +16 -0
  268. package/tests/HybridComponent.browser-test.js +214 -214
  269. package/tests/LightComponent.browser-test.js +169 -169
  270. package/tests/ShadowComponent.browser-test.js +130 -130
  271. package/config/development.json +0 -14
  272. package/docs/components/ShadowComponent.js +0 -1
  273. package/src/utils/cli.js +0 -43
  274. package/src/utils/fs-utils.js +0 -41
  275. /package/{docs → dist/src}/components/HybridComponent.js +0 -0
  276. /package/{docs → dist/src}/components/LightComponent.js +0 -0
  277. /package/docs/{utils → src/utils}/cli.js +0 -0
  278. /package/docs/{utils → src/utils}/fs-utils.js +0 -0
@@ -0,0 +1,108 @@
1
+ import ShadowComponent from './ShadowComponent.js';
2
+ import { html, css } from '../lit-all.min.js';
3
+ import './Icon.js';
4
+
5
+ export default class ThemeSwitcher extends ShadowComponent {
6
+ /*
7
+ Properties
8
+ */
9
+ static properties = {
10
+ currentTheme: { type: String, reflect: true, attribute: 'current-theme' }
11
+ };
12
+
13
+ constructor() {
14
+ super();
15
+ this.currentTheme = ThemeSwitcher.getCurrentTheme();
16
+ }
17
+
18
+ /*
19
+ Event Handlers
20
+ */
21
+ handleClick = () => {
22
+ const current = ThemeSwitcher.getCurrentTheme();
23
+ if(current === 'auto') ThemeSwitcher.setTheme('light');
24
+ if(current === 'light') ThemeSwitcher.setTheme('dark');
25
+ if(current === 'dark') ThemeSwitcher.setTheme('auto');
26
+ }
27
+
28
+ handleStorageChange = () => {
29
+ this.currentTheme = ThemeSwitcher.getCurrentTheme();
30
+ }
31
+
32
+ /*
33
+ Lifecycle Callbacks
34
+ */
35
+ connectedCallback() {
36
+ super.connectedCallback();
37
+ window.addEventListener('storage', this.handleStorageChange);
38
+ }
39
+
40
+ disconnectedCallback() {
41
+ super.disconnectedCallback();
42
+ window.removeEventListener('storage', this.handleStorageChange);
43
+ }
44
+
45
+ /*
46
+ Styles
47
+ */
48
+ static styles = css`
49
+ :host {
50
+ --padding: var(--spacer);
51
+ display: flex;
52
+ }
53
+ button {
54
+ padding: var(--padding);
55
+ }
56
+ `;
57
+
58
+ /*
59
+ Rendering
60
+ */
61
+ render() {
62
+ const iconName = this.currentTheme === 'auto' ? 'mode-auto' :
63
+ this.currentTheme === 'light' ? 'mode-light' : 'mode-dark';
64
+
65
+ return html`
66
+ <button
67
+ class="no-btn"
68
+ @click=${this.handleClick}
69
+ >
70
+ <k-icon name=${iconName}></k-icon>
71
+ </button>
72
+ `;
73
+ }
74
+ static styles = css`
75
+ :host {
76
+ --padding: var(--spacer, 1rem);
77
+ }
78
+ button.no-btn {
79
+ padding: var(--padding);
80
+ }
81
+ `;
82
+
83
+ /*
84
+ Static Methods
85
+ */
86
+ static setTheme(theme) {
87
+ localStorage.setItem('theme', theme);
88
+ document.documentElement.setAttribute('theme', theme);
89
+ window.dispatchEvent(new StorageEvent('storage', { key: 'theme', newValue: theme }));
90
+ }
91
+
92
+ static getCurrentTheme() {
93
+ let theme = document.documentElement.getAttribute('theme');
94
+ if(!theme) theme = localStorage.getItem('theme');
95
+ return theme || 'auto';
96
+ }
97
+ }
98
+
99
+ /*
100
+ Auto Theme Detection
101
+ */
102
+ const colorSchemeQuery = window.matchMedia('(prefers-color-scheme: dark)');
103
+ const colorSchemeChangeHandler = event => document.documentElement.setAttribute('auto-theme', event.matches ? 'dark' : 'light');
104
+ colorSchemeQuery.addEventListener('change', colorSchemeChangeHandler);
105
+ colorSchemeChangeHandler(colorSchemeQuery);
106
+
107
+ ThemeSwitcher.setTheme(ThemeSwitcher.getCurrentTheme());
108
+ customElements.define('k-theme-switcher', ThemeSwitcher);
@@ -0,0 +1,31 @@
1
+ import { html } from '../lit-all.min.js';
2
+ import ShadowComponent from './ShadowComponent.js';
3
+ import formatTimestamp from '../utils/formatTimestamp.js';
4
+
5
+ export default class Timestamp extends ShadowComponent {
6
+ static properties = {
7
+ timestamp: { type: Number, reflect: true },
8
+ format: { type: String, reflect: true },
9
+ locale: { type: String, reflect: true }
10
+ };
11
+
12
+ constructor() {
13
+ super();
14
+ this.timestamp = 0;
15
+ this.format = '';
16
+ this.locale = '';
17
+ }
18
+
19
+ /*
20
+ Rendering Logic
21
+ */
22
+ render() {
23
+ const formattedTime = this.timestamp
24
+ ? formatTimestamp(this.timestamp, this.format, this.locale || navigator.language)
25
+ : '';
26
+
27
+ return html`<span>${formattedTime}</span>`;
28
+ }
29
+ }
30
+
31
+ window.customElements.define('k-timestamp', Timestamp);
@@ -0,0 +1,454 @@
1
+ import { html, css } from '../lit-all.min.js';
2
+ import ShadowComponent from './ShadowComponent.js';
3
+ import './Icon.js';
4
+
5
+ export default class Toast extends ShadowComponent {
6
+ static properties = {
7
+ actionHtml: { type: String, reflect: true, attribute: 'action-html' },
8
+ closeHtml: { type: String, reflect: true, attribute: 'close-html' },
9
+ timeout: { type: Number, reflect: true },
10
+ opened: { type: Boolean, reflect: true },
11
+ hasAction: { type: Boolean, reflect: true, attribute: 'has-action' },
12
+ hasClose: { type: Boolean, reflect: true, attribute: 'has-close' },
13
+ hasIcon: { type: Boolean, reflect: true, attribute: 'has-icon' },
14
+ position: { type: String, reflect: true },
15
+ animating: { type: String, reflect: true }
16
+ };
17
+
18
+ static styles = css`
19
+ @keyframes toast-show-bottom {
20
+ from { opacity: 0; transform: translateY(20px); }
21
+ to { opacity: 1; transform: translateY(0); }
22
+ }
23
+ @keyframes toast-hide-bottom {
24
+ from { opacity: 1; transform: translateY(0); }
25
+ to { opacity: 0; transform: translateY(20px); }
26
+ }
27
+ @keyframes toast-show-top {
28
+ from { opacity: 0; transform: translateY(-20px); }
29
+ to { opacity: 1; transform: translateY(0); }
30
+ }
31
+ @keyframes toast-hide-top {
32
+ from { opacity: 1; transform: translateY(0); }
33
+ to { opacity: 0; transform: translateY(-20px); }
34
+ }
35
+ @keyframes toast-show-left {
36
+ from { opacity: 0; transform: translateX(-20px); }
37
+ to { opacity: 1; transform: translateX(0); }
38
+ }
39
+ @keyframes toast-hide-left {
40
+ from { opacity: 1; transform: translateX(0); }
41
+ to { opacity: 0; transform: translateX(-20px); }
42
+ }
43
+ @keyframes toast-show-right {
44
+ from { opacity: 0; transform: translateX(20px); }
45
+ to { opacity: 1; transform: translateX(0); }
46
+ }
47
+ @keyframes toast-hide-right {
48
+ from { opacity: 1; transform: translateX(0); }
49
+ to { opacity: 0; transform: translateX(20px); }
50
+ }
51
+
52
+ :host {
53
+ display: none;
54
+ min-width: 16rem;
55
+ max-width: calc(100% - (2 * var(--spacer, 1rem)));
56
+ background-color: var(--c_bg, #ffffff);
57
+ border-radius: var(--radius, 0.375rem);
58
+ }
59
+
60
+ :host([opened]) {
61
+ display: flex;
62
+ }
63
+
64
+ :host([animating="in"][position*="bottom"]) {
65
+ animation: toast-show-bottom var(--animation_ms, 300ms) ease forwards;
66
+ }
67
+ :host([animating="out"][position*="bottom"]) {
68
+ animation: toast-hide-bottom var(--animation_ms, 300ms) ease forwards;
69
+ }
70
+ :host([animating="in"][position*="top"]) {
71
+ animation: toast-show-top var(--animation_ms, 300ms) ease forwards;
72
+ }
73
+ :host([animating="out"][position*="top"]) {
74
+ animation: toast-hide-top var(--animation_ms, 300ms) ease forwards;
75
+ }
76
+ :host([animating="in"][position*="left"]:not([position*="top"]):not([position*="bottom"])) {
77
+ animation: toast-show-left var(--animation_ms, 300ms) ease forwards;
78
+ }
79
+ :host([animating="out"][position*="left"]:not([position*="top"]):not([position*="bottom"])) {
80
+ animation: toast-hide-left var(--animation_ms, 300ms) ease forwards;
81
+ }
82
+ :host([animating="in"][position*="right"]:not([position*="top"]):not([position*="bottom"])) {
83
+ animation: toast-show-right var(--animation_ms, 300ms) ease forwards;
84
+ }
85
+ :host([animating="out"][position*="right"]:not([position*="top"]):not([position*="bottom"])) {
86
+ animation: toast-hide-right var(--animation_ms, 300ms) ease forwards;
87
+ }
88
+
89
+ #icon {
90
+ padding: var(--spacer, 1rem);
91
+ padding-right: 0;
92
+ }
93
+
94
+ #message {
95
+ padding: var(--spacer, 1rem);
96
+ flex: 1 1 auto;
97
+ }
98
+
99
+ :host(:not([has-close])) #close,
100
+ :host(:not([has-action])) #action,
101
+ :host(:not([has-icon])) #icon {
102
+ display: none;
103
+ }
104
+
105
+ #action {
106
+ background: transparent;
107
+ border: none;
108
+ color: var(--tc_primary, blue);
109
+ cursor: pointer;
110
+ padding: var(--spacer, 1rem);
111
+ }
112
+
113
+ #action:hover {
114
+ color: var(--tc_primary__hover, lightblue);
115
+ }
116
+
117
+ #close {
118
+ background: transparent;
119
+ border: none;
120
+ cursor: pointer;
121
+ padding: var(--spacer, 1rem);
122
+ opacity: 0.7;
123
+ transition: opacity var(--animation_ms, 300ms);
124
+ }
125
+
126
+ #close:hover {
127
+ opacity: 1;
128
+ }
129
+
130
+ /* Theme classes */
131
+ :host(.bg-success) {
132
+ background-color: var(--c_success, #dcfce7);
133
+ color: var(--tc_on_success, #166534);
134
+ }
135
+
136
+ :host(.bg-warning) {
137
+ background-color: var(--c_warning, #fef3c7);
138
+ color: var(--tc_on_warning, #92400e);
139
+ }
140
+
141
+ :host(.bg-danger) {
142
+ background-color: var(--c_danger, #fee2e2);
143
+ color: var(--tc_on_danger, #991b1b);
144
+ }
145
+ `;
146
+
147
+ constructor() {
148
+ super();
149
+ this.actionHtml = '';
150
+ this.closeHtml = '';
151
+ this.timeout = 0;
152
+ this.opened = false;
153
+ this.hasAction = false;
154
+ this.hasClose = false;
155
+ this.hasIcon = false;
156
+ this.position = 'bottom center';
157
+ this.animating = '';
158
+ this.actionCallback = () => {};
159
+ this.closeCallback = () => {};
160
+ this.timeoutId = null;
161
+ this.closing = false;
162
+ }
163
+
164
+ /*
165
+ Lifecycle Methods
166
+ */
167
+ updated(changedProperties) {
168
+ super.updated(changedProperties);
169
+
170
+ if (changedProperties.has('opened') && this.opened) {
171
+ this.hasAction = !!this.querySelector('[slot="action"]');
172
+ this.hasClose = !!this.querySelector('[slot="close"]');
173
+ this.hasIcon = !!this.querySelector('[slot="icon"]');
174
+ }
175
+ }
176
+
177
+ connectedCallback() {
178
+ super.connectedCallback();
179
+ this.addEventListener('animationend', this.handleAnimationEnd);
180
+ }
181
+
182
+ disconnectedCallback() {
183
+ super.disconnectedCallback();
184
+ this.removeEventListener('animationend', this.handleAnimationEnd);
185
+ clearTimeout(this.timeoutId);
186
+ }
187
+
188
+ /*
189
+ Event Handlers
190
+ */
191
+ handleActionClick = () => {
192
+ if (this.actionCallback() !== false) {
193
+ this.close();
194
+ }
195
+ };
196
+
197
+ handleCloseClick = () => {
198
+ this.close();
199
+ };
200
+
201
+ handleAnimationEnd = (e) => {
202
+ if (e.animationName.includes('toast-hide')) {
203
+ this.animating = '';
204
+ this.opened = false;
205
+ this.dispatchEvent(new CustomEvent('close'));
206
+ this.dispatchEvent(new CustomEvent('openchange'));
207
+ this.closeCallback();
208
+ this.closing = false;
209
+ } else if (e.animationName.includes('toast-show')) {
210
+ this.animating = '';
211
+ }
212
+ };
213
+
214
+ /*
215
+ Public Methods
216
+ */
217
+ open() {
218
+ this.closing = false;
219
+ this.animating = 'in';
220
+ this.opened = true;
221
+
222
+ if (this.timeout) {
223
+ clearTimeout(this.timeoutId);
224
+ this.timeoutId = setTimeout(() => {
225
+ this.close();
226
+ }, this.timeout);
227
+ }
228
+
229
+ this.dispatchEvent(new CustomEvent('open'));
230
+ this.dispatchEvent(new CustomEvent('openchange'));
231
+ }
232
+
233
+ close() {
234
+ clearTimeout(this.timeoutId);
235
+ if (this.opened && !this.closing) {
236
+ this.closing = true;
237
+ this.animating = 'out';
238
+ // opened will be set to false in the animation end handler
239
+ }
240
+ }
241
+
242
+ /*
243
+ Rendering Logic
244
+ */
245
+ render() {
246
+ return html`
247
+ <div id="icon">
248
+ <slot name="icon"></slot>
249
+ </div>
250
+ <div id="message">
251
+ <slot></slot>
252
+ </div>
253
+ <button id="action" class="no-style" @click="${this.handleActionClick}">
254
+ <slot name="action"></slot>
255
+ </button>
256
+ <button id="close" class="no-style" @click="${this.handleCloseClick}">
257
+ <slot name="close"></slot>
258
+ </button>
259
+ `;
260
+ }
261
+
262
+ /*
263
+ Static Methods
264
+ */
265
+ static create(message, options = {}) {
266
+ let {
267
+ position = 'auto',
268
+ removeOnClose = true,
269
+ closeCallback = () => {},
270
+ action = false,
271
+ close = false,
272
+ icon = false,
273
+ timeout = 5000
274
+ } = options;
275
+
276
+ if (position === 'auto') {
277
+ position = window.innerWidth <= 768 ? 'bottom center' : 'top right';
278
+ }
279
+
280
+ let container = document.querySelector(`k-toast-container[position="${position}"]`);
281
+ if (!container) {
282
+ container = new ToastContainer(position);
283
+ document.body.appendChild(container);
284
+ }
285
+
286
+ const toast = new Toast();
287
+ toast.position = position;
288
+ toast.timeout = timeout;
289
+ toast.innerHTML = message;
290
+
291
+ // Set callbacks
292
+ toast.actionCallback = options.actionCallback || (() => {});
293
+ const originalCloseCallback = closeCallback;
294
+ toast.closeCallback = (...args) => {
295
+ if (removeOnClose) {
296
+ toast.remove();
297
+ if (container.children.length === 0) {
298
+ container.remove();
299
+ }
300
+ }
301
+ originalCloseCallback(...args);
302
+ };
303
+
304
+ // Add icon
305
+ if (icon) {
306
+ const iconElement = document.createElement('span');
307
+ iconElement.slot = 'icon';
308
+ if (icon instanceof HTMLElement) {
309
+ iconElement.appendChild(icon);
310
+ } else {
311
+ iconElement.innerHTML = icon;
312
+ }
313
+ toast.appendChild(iconElement);
314
+ }
315
+
316
+ // Add action
317
+ if (action) {
318
+ const actionElement = document.createElement('span');
319
+ actionElement.slot = 'action';
320
+ if (action instanceof HTMLElement) {
321
+ actionElement.appendChild(action);
322
+ } else {
323
+ actionElement.innerHTML = action;
324
+ }
325
+ toast.appendChild(actionElement);
326
+ }
327
+
328
+ // Add close
329
+ if (close) {
330
+ const closeElement = document.createElement('span');
331
+ closeElement.slot = 'close';
332
+ if (close instanceof HTMLElement) {
333
+ closeElement.appendChild(close);
334
+ } else {
335
+ closeElement.innerHTML = close;
336
+ }
337
+ toast.appendChild(closeElement);
338
+ }
339
+
340
+ container.appendChild(toast);
341
+ toast.open();
342
+ return toast;
343
+ }
344
+
345
+ static success(message, options = {}) {
346
+ const toast = Toast.create(message, {
347
+ icon: '<k-icon name="check"></k-icon>',
348
+ ...options
349
+ });
350
+ toast.classList.add('bg-success');
351
+ return toast;
352
+ }
353
+
354
+ static warning(message, options = {}) {
355
+ const toast = Toast.create(message, {
356
+ icon: '<k-icon name="warning"></k-icon>',
357
+ ...options
358
+ });
359
+ toast.classList.add('bg-warning');
360
+ return toast;
361
+ }
362
+
363
+ static error(message, options = {}) {
364
+ const toast = Toast.create(message, {
365
+ icon: '<k-icon name="error"></k-icon>',
366
+ ...options
367
+ });
368
+ toast.classList.add('bg-danger');
369
+ return toast;
370
+ }
371
+ }
372
+
373
+ class ToastContainer extends HTMLElement {
374
+ constructor(position = 'bottom center') {
375
+ super();
376
+ this.position = position.toLowerCase();
377
+ this.setAttribute('position', this.position);
378
+ this.applyStyles();
379
+ }
380
+
381
+ applyStyles() {
382
+ this.style.cssText = `
383
+ position: fixed;
384
+ display: flex;
385
+ flex-direction: column;
386
+ gap: 8px;
387
+ z-index: 1000;
388
+ pointer-events: auto;
389
+ padding: 32px;
390
+ box-sizing: border-box;
391
+ max-width: 100%;
392
+ max-height: 100%;
393
+ overflow: visible;
394
+ `;
395
+
396
+ const observer = new MutationObserver(() => {
397
+ Array.from(this.children).forEach(toast => {
398
+ if (toast.tagName === 'K-TOAST') {
399
+ toast.style.filter = 'drop-shadow(0 10px 15px rgba(0, 0, 0, 0.1)) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.05))';
400
+ }
401
+ });
402
+ });
403
+
404
+ observer.observe(this, { childList: true });
405
+
406
+ // Apply to existing children
407
+ Array.from(this.children).forEach(toast => {
408
+ if (toast.tagName === 'K-TOAST') {
409
+ toast.style.filter = 'drop-shadow(0 10px 15px rgba(0, 0, 0, 0.1)) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.05))';
410
+ }
411
+ });
412
+
413
+ const [vertical, horizontal] = this.position.split(' ');
414
+
415
+ // Vertical positioning
416
+ if (vertical === 'top') {
417
+ this.style.top = '0';
418
+ } else {
419
+ this.style.bottom = '0';
420
+ }
421
+
422
+ // Horizontal positioning
423
+ if (horizontal === 'left') {
424
+ this.style.left = '0';
425
+ this.style.alignItems = 'flex-start';
426
+ } else if (horizontal === 'right') {
427
+ this.style.right = '0';
428
+ this.style.alignItems = 'flex-end';
429
+ } else if (horizontal === 'center') {
430
+ if (vertical === 'top' || vertical === 'bottom') {
431
+ this.style.left = '50%';
432
+ this.style.transform = 'translateX(-50%)';
433
+ this.style.alignItems = 'center';
434
+ } else {
435
+ this.style.top = '50%';
436
+ this.style.left = '50%';
437
+ this.style.transform = 'translate(-50%, -50%)';
438
+ }
439
+ }
440
+ }
441
+
442
+ static getContainer(position) {
443
+ let container = document.querySelector(`k-toast-container[position="${position}"]`);
444
+ if (!container) {
445
+ container = new ToastContainer(position);
446
+ document.body.appendChild(container);
447
+ }
448
+ return container;
449
+ }
450
+ }
451
+
452
+ // Register custom elements
453
+ window.customElements.define('k-toast', Toast);
454
+ window.customElements.define('k-toast-container', ToastContainer);