@vverchonov/web-components 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/button-DYrT530y.js +39 -0
  2. package/dist/button.js +2 -0
  3. package/dist/components/button/button-types.d.ts +2 -0
  4. package/dist/components/button/button.d.ts +14 -0
  5. package/dist/components/button/index.d.ts +2 -0
  6. package/dist/components/dropdown-button/dropdown-button-types.d.ts +13 -0
  7. package/dist/components/dropdown-button/dropdown-button.d.ts +34 -0
  8. package/dist/components/dropdown-button/index.d.ts +2 -0
  9. package/dist/components/input/index.d.ts +2 -0
  10. package/dist/components/input/input-types.d.ts +2 -0
  11. package/dist/components/input/input.d.ts +22 -0
  12. package/dist/components/layouts/form/form-layout-types.d.ts +3 -0
  13. package/dist/components/layouts/form/form-layout.d.ts +53 -0
  14. package/dist/components/layouts/form/index.d.ts +2 -0
  15. package/dist/components/layouts/index.d.ts +3 -0
  16. package/dist/components/layouts/page/index.d.ts +1 -0
  17. package/dist/components/layouts/page/layout.d.ts +20 -0
  18. package/dist/components/menu/index.d.ts +2 -0
  19. package/dist/components/menu/menu-types.d.ts +16 -0
  20. package/dist/components/menu/menu.d.ts +36 -0
  21. package/dist/components/modal/index.d.ts +2 -0
  22. package/dist/components/modal/modal-types.d.ts +2 -0
  23. package/dist/components/modal/modal.d.ts +103 -0
  24. package/dist/components/selector/index.d.ts +2 -0
  25. package/dist/components/selector/selector-types.d.ts +19 -0
  26. package/dist/components/selector/selector.d.ts +56 -0
  27. package/dist/components/table/index.d.ts +2 -0
  28. package/dist/components/table/table-types.d.ts +35 -0
  29. package/dist/components/table/table.d.ts +47 -0
  30. package/dist/components/tabs/index.d.ts +2 -0
  31. package/dist/components/tabs/tabs.d.ts +19 -0
  32. package/dist/components/toggle/index.d.ts +2 -0
  33. package/dist/components/toggle/toggle-types.d.ts +4 -0
  34. package/dist/components/toggle/toggle.d.ts +15 -0
  35. package/dist/dropdown-button-B6XNoy4L.js +172 -0
  36. package/dist/dropdown-button.js +2 -0
  37. package/dist/form-layout-DCX8X-8-.js +140 -0
  38. package/dist/index.d.ts +22 -0
  39. package/dist/input-BVlPYqTe.js +70 -0
  40. package/dist/input.js +2 -0
  41. package/dist/layout-CYvgu_WE.js +23 -0
  42. package/dist/layouts.js +3 -0
  43. package/dist/menu-DmAFaVi5.js +248 -0
  44. package/dist/menu.js +2 -0
  45. package/dist/mock/table-data.d.ts +16 -0
  46. package/dist/modal-v1GlqMF_.js +174 -0
  47. package/dist/modal.js +2 -0
  48. package/dist/react/button.d.ts +2 -0
  49. package/dist/react/button.js +9 -0
  50. package/dist/react/dropdown-button.d.ts +6 -0
  51. package/dist/react/dropdown-button.js +10 -0
  52. package/dist/react/form-layout.d.ts +8 -0
  53. package/dist/react/form-layout.js +14 -0
  54. package/dist/react/index.d.ts +21 -0
  55. package/dist/react/input.d.ts +2 -0
  56. package/dist/react/input.js +9 -0
  57. package/dist/react/layout.d.ts +2 -0
  58. package/dist/react/layout.js +9 -0
  59. package/dist/react/menu.d.ts +7 -0
  60. package/dist/react/menu.js +13 -0
  61. package/dist/react/modal.d.ts +7 -0
  62. package/dist/react/modal.js +14 -0
  63. package/dist/react/selector.d.ts +6 -0
  64. package/dist/react/selector.js +10 -0
  65. package/dist/react/table.d.ts +8 -0
  66. package/dist/react/table.js +14 -0
  67. package/dist/react/tabs.d.ts +5 -0
  68. package/dist/react/tabs.js +10 -0
  69. package/dist/react/toggle.d.ts +6 -0
  70. package/dist/react/toggle.js +10 -0
  71. package/dist/react.js +12 -0
  72. package/dist/selector-Bl7Nbkqo.js +300 -0
  73. package/dist/selector.js +2 -0
  74. package/dist/styles/tailwind-base.d.ts +1 -0
  75. package/dist/table--O5km0Wv.js +279 -0
  76. package/dist/table.js +2 -0
  77. package/dist/tabs-C2lP0uxY.js +94 -0
  78. package/dist/tabs.js +2 -0
  79. package/dist/toggle-D6UMZ8UZ.js +59 -0
  80. package/dist/toggle.js +2 -0
  81. package/dist/vite.svg +1 -0
  82. package/dist/web-components.js +24 -0
  83. package/package.json +153 -0
@@ -0,0 +1,248 @@
1
+ import { LitElement as e, html as t, nothing as n, unsafeCSS as r } from "lit";
2
+ import { customElement as i, property as a, state as o } from "lit/decorators.js";
3
+ import { repeat as s } from "lit/directives/repeat.js";
4
+ var c = ":host{width:var(--menu-width,240px);background:var(--menu-bg,var(--color-surface));border-right:1px solid var(--color-border);box-sizing:border-box;height:100%;transition:width .25s var(--ease-emphasized);flex-direction:column;font-family:inherit;display:flex;overflow:hidden}:host(.is-collapsed){width:var(--menu-collapsed-width,3.5rem)}.logo-wrapper{padding:var(--menu-logo-padding,1rem);border-bottom:1px solid var(--color-border);flex-shrink:0;justify-content:flex-start;align-items:center;min-height:3.5rem;display:flex;overflow:hidden}:host(.is-collapsed) .logo-wrapper{justify-content:center;padding-inline:.5rem}.logo-wrapper:not(:has(slot[name=logo]>*)):not(:has(slot[name=logo-icon]>*)){display:none}.logo-expanded,.logo-icon{align-items:center;min-width:0;display:flex}:host(.is-collapsed) .logo-expanded,:host(:not(.is-collapsed)) .logo-icon{display:none}:host(.is-collapsed) .logo-wrapper:not(:has(slot[name=logo-icon]>*)) .logo-expanded{display:flex}.search-wrapper{padding:var(--menu-search-padding,.75rem);border-bottom:1px solid var(--color-border);transition:opacity .15s var(--ease-emphasized-out);flex-shrink:0;align-items:center;gap:.5rem;display:flex;overflow:hidden}:host(.is-collapsed) .search-wrapper{opacity:0;pointer-events:none;border-bottom-width:0;max-height:0;padding-block:0}.search-icon{color:var(--color-text-muted);flex-shrink:0;align-items:center;display:flex}.search-input{background:var(--color-surface-elevated);border:1px solid var(--color-border);border-radius:var(--radius-input);min-width:0;font-size:var(--menu-item-font-size,.875rem);color:var(--color-text);appearance:none;outline:none;flex:1;padding:.375rem .5rem;transition:border-color .15s,box-shadow .15s}.search-input::placeholder{color:var(--color-text-muted)}.search-input:hover{border-color:var(--color-border-strong)}.search-input:focus-visible{outline:2px solid var(--color-primary);outline-offset:1px;border-color:var(--color-primary)}.search-input::-webkit-search-cancel-button{-webkit-appearance:none}.nav-main{flex:1;padding-block:.5rem;overflow:hidden auto}.nav-footer{border-top:1px solid var(--color-border);flex-shrink:0;padding-block:.5rem}.menu,.submenu{margin:0;padding:0;list-style:none}.menu-item-wrapper{display:block}.menu-item{align-items:center;gap:var(--menu-item-icon-gap,.625rem);padding-block:var(--menu-item-padding-block,.5rem);padding-inline:var(--menu-item-padding-inline,.75rem);border-radius:var(--radius-button);width:calc(100% - .5rem);font-size:var(--menu-item-font-size,.875rem);color:var(--color-text);text-align:left;cursor:pointer;transition:background-color .15s var(--ease-emphasized-out), color .15s var(--ease-emphasized-out);box-sizing:border-box;white-space:nowrap;background:0 0;border:none;min-height:2.25rem;margin-inline:.25rem;padding-inline-start:calc(var(--menu-item-padding-inline,.75rem) + var(--depth,0) * var(--menu-indent,1rem));font-weight:400;text-decoration:none;display:flex;overflow:hidden}.menu-item:hover{background:var(--color-surface-elevated);color:var(--color-text)}.menu-item.is-active{background:var(--color-primary-muted);color:var(--color-primary);font-weight:500}.menu-item.is-active:hover{background:var(--color-primary-muted)}.menu-item:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px}:host(.is-collapsed) .menu-item{justify-content:center;gap:0;width:100%;margin-inline:0;padding-inline:0}.item-icon{color:inherit;flex-shrink:0;align-items:center;display:flex}.item-label{text-overflow:ellipsis;white-space:nowrap;opacity:1;min-width:0;transition:opacity .1s var(--ease-emphasized-out) .1s;flex:1;overflow:hidden}:host(.is-collapsed) .item-label{opacity:0;width:0;min-width:0;transition:opacity 50ms var(--ease-emphasized-in);flex:0 0 0;overflow:hidden}.submenu-indicator{color:var(--color-text-muted);opacity:1;transition:transform .2s var(--ease-emphasized), opacity .1s var(--ease-emphasized-out) .1s;flex-shrink:0;align-items:center;margin-inline-start:auto;display:flex}.menu-item.is-expanded .submenu-indicator{transform:rotate(180deg)}:host(.is-collapsed) .submenu-indicator{opacity:0;width:0;min-width:0;transition:opacity 50ms var(--ease-emphasized-in);flex:0 0 0;margin:0;overflow:hidden}.submenu{max-height:0;transition:max-height .25s var(--ease-emphasized-out);overflow:hidden}.submenu.is-open{max-height:9999px;transition:max-height .35s var(--ease-emphasized)}:host(.is-collapsed) .submenu{transition:none;max-height:0!important}.menu:empty:after{padding:.5rem var(--menu-item-padding-inline,.75rem);font-size:var(--menu-item-font-size,.875rem);color:var(--color-text-muted);content:\"No results\";display:block}:host(.is-collapsed) .menu:empty:after{display:none}.bottom-slot{border-top:1px solid var(--color-border);padding:var(--menu-item-padding-block,.5rem) var(--menu-item-padding-inline,.75rem);flex-shrink:0;align-items:center;display:flex;overflow:hidden}.bottom-slot.is-empty{display:none}:host(.is-collapsed) .bottom-slot{justify-content:center;padding-inline:0}:host(.is-collapsed) ::slotted(app-toggle){--toggle-label-display:none;--toggle-track-display:none}.sr-only{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}";
5
+ function l(e, t, n, r) {
6
+ var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
7
+ if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
8
+ else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
9
+ return i > 3 && a && Object.defineProperty(t, n, a), a;
10
+ }
11
+ var u = t`
12
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
13
+ <polyline points="6 9 12 15 18 9"></polyline>
14
+ </svg>
15
+ `, d = t`
16
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
17
+ <circle cx="11" cy="11" r="8"></circle>
18
+ <line x1="21" y1="21" x2="16.65" y2="16.65"></line>
19
+ </svg>
20
+ `;
21
+ function f(e, t) {
22
+ if (!t) return !0;
23
+ let n = t.toLowerCase();
24
+ return e.label.toLowerCase().includes(n) ? !0 : e.children?.some((e) => f(e, t)) ?? !1;
25
+ }
26
+ function p(e, t) {
27
+ return t ? e.reduce((e, n) => (n.label.toLowerCase().includes(t.toLowerCase()) ? e.push(n) : n.children?.some((e) => f(e, t)) && e.push({
28
+ ...n,
29
+ children: p(n.children, t)
30
+ }), e), []) : e;
31
+ }
32
+ var m = class extends e {
33
+ static {
34
+ this.styles = [r(c)];
35
+ }
36
+ get _isCollapsed() {
37
+ return this.collapsed && !this._hoverExpanded;
38
+ }
39
+ connectedCallback() {
40
+ super.connectedCallback(), this.addEventListener("mouseenter", this._onMouseEnter), this.addEventListener("mouseleave", this._onMouseLeave);
41
+ }
42
+ disconnectedCallback() {
43
+ super.disconnectedCallback(), this.removeEventListener("mouseenter", this._onMouseEnter), this.removeEventListener("mouseleave", this._onMouseLeave);
44
+ }
45
+ updated() {
46
+ if (this.classList.toggle("is-collapsed", this._isCollapsed), !this._isCollapsed && this.activeValue != null) {
47
+ let e = this._getPathToActiveValue(this.items, this.activeValue, "m") ?? this._getPathToActiveValue(this.footerItems, this.activeValue, "f") ?? null;
48
+ if (e) {
49
+ let t = e.split("-"), n = /* @__PURE__ */ new Set();
50
+ for (let e = 2; e < t.length; e++) n.add(t.slice(0, e).join("-"));
51
+ n.size > 0 && [...n].some((e) => !this._openPaths.has(e)) && (this._openPaths = new Set([...this._openPaths, ...n]));
52
+ }
53
+ }
54
+ }
55
+ _itemContainsActiveValue(e) {
56
+ return this.activeValue == null ? !1 : e.value === this.activeValue ? !0 : e.children?.some((e) => this._itemContainsActiveValue(e)) ?? !1;
57
+ }
58
+ _getPathToActiveValue(e, t, n) {
59
+ for (let r = 0; r < e.length; r++) {
60
+ let i = e[r], a = `${n}-${r}`;
61
+ if (i.value === t) return a;
62
+ if (i.children?.length) {
63
+ let e = this._getPathToActiveValue(i.children, t, a);
64
+ if (e) return e;
65
+ }
66
+ }
67
+ return null;
68
+ }
69
+ _toggleSubmenu(e) {
70
+ let t = new Set(this._openPaths);
71
+ if (t.has(e)) for (let n of [...t]) (n === e || n.startsWith(`${e}-`)) && t.delete(n);
72
+ else t.add(e);
73
+ this._openPaths = t;
74
+ }
75
+ _onItemClick(e, t) {
76
+ if (e.children?.length) {
77
+ this._toggleSubmenu(t);
78
+ return;
79
+ }
80
+ this.dispatchEvent(new CustomEvent("menu-select", {
81
+ detail: {
82
+ item: e,
83
+ value: e.value
84
+ },
85
+ bubbles: !0,
86
+ composed: !0
87
+ }));
88
+ }
89
+ _onSearchInput(e) {
90
+ this._searchQuery = e.target.value, this.dispatchEvent(new CustomEvent("menu-search", {
91
+ detail: { query: this._searchQuery },
92
+ bubbles: !0,
93
+ composed: !0
94
+ }));
95
+ }
96
+ _onNavKeydown(e) {
97
+ let t = e.target;
98
+ if (!t.classList.contains("menu-item")) return;
99
+ let n = t.closest(".menu-item-wrapper"), r = n?.getAttribute("data-path") ?? "", i = n?.parentElement, a = i ? Array.from(i.children).map((e) => e.querySelector(":scope > .menu-item")).filter(Boolean) : [], o = !!n?.querySelector(":scope > .submenu");
100
+ switch (e.key) {
101
+ case "ArrowDown": {
102
+ e.preventDefault();
103
+ let n = a.indexOf(t);
104
+ n < a.length - 1 && a[n + 1].focus();
105
+ break;
106
+ }
107
+ case "ArrowUp": {
108
+ e.preventDefault();
109
+ let n = a.indexOf(t);
110
+ n > 0 && a[n - 1].focus();
111
+ break;
112
+ }
113
+ case "ArrowRight":
114
+ case "Enter":
115
+ o && !this._openPaths.has(r) && (e.preventDefault(), this._toggleSubmenu(r), this.updateComplete.then(() => {
116
+ (n?.querySelector(":scope > .submenu > .menu-item-wrapper > .menu-item"))?.focus();
117
+ }));
118
+ break;
119
+ case "ArrowLeft": {
120
+ e.preventDefault();
121
+ let t = r.split("-");
122
+ if (t.length > 2) {
123
+ let e = t.slice(0, -1).join("-"), n = new Set(this._openPaths);
124
+ for (let e of [...n]) (e === r || e.startsWith(`${r}-`)) && n.delete(e);
125
+ this._openPaths = n, this.shadowRoot?.querySelector(`.menu-item-wrapper[data-path="${e}"] > .menu-item`)?.focus();
126
+ }
127
+ break;
128
+ }
129
+ case "Escape":
130
+ if (e.preventDefault(), this._openPaths.size > 0) {
131
+ let e = [...this._openPaths].sort((e, t) => t.split("-").length - e.split("-").length)[0], t = new Set(this._openPaths);
132
+ for (let n of [...t]) (n === e || n.startsWith(`${e}-`)) && t.delete(n);
133
+ this._openPaths = t;
134
+ }
135
+ break;
136
+ default: break;
137
+ }
138
+ }
139
+ _renderItemIcon(e) {
140
+ return e.icon == null ? t`` : typeof e.icon == "string" ? t`<span class="item-icon"><slot name=${`icon-${e.icon}`}></slot></span>` : t`<span class="item-icon">${e.icon}</span>`;
141
+ }
142
+ _renderItems(e, r, i) {
143
+ return t`${s(e, (e, t) => `${r}-${t}-${e.label}`, (e, a) => {
144
+ let o = `${r}-${a}`, s = !!e.children?.length, c = this._openPaths.has(o), l = this.activeValue != null && (e.value === this.activeValue || s && this._itemContainsActiveValue(e)), d = this.activeValue != null && e.value === this.activeValue;
145
+ return t`
146
+ <li class="menu-item-wrapper" data-path=${o} role="none">
147
+ ${e.href && !s ? t`
148
+ <a
149
+ href=${e.href}
150
+ class="menu-item ${l ? "is-active" : ""}"
151
+ role="treeitem"
152
+ aria-current=${d ? "page" : n}
153
+ title=${e.label}
154
+ style="--depth: ${i}"
155
+ @click=${() => this._onItemClick(e, o)}
156
+ >
157
+ ${this._renderItemIcon(e)}
158
+ <span class="item-label">${e.label}</span>
159
+ </a>
160
+ ` : t`
161
+ <button
162
+ type="button"
163
+ class="menu-item ${l ? "is-active" : ""} ${s ? "has-children" : ""} ${c ? "is-expanded" : ""}"
164
+ role="treeitem"
165
+ aria-expanded=${s ? c ? "true" : "false" : n}
166
+ aria-current=${d ? "page" : n}
167
+ title=${e.label}
168
+ style="--depth: ${i}"
169
+ @click=${() => this._onItemClick(e, o)}
170
+ >
171
+ ${this._renderItemIcon(e)}
172
+ <span class="item-label">${e.label}</span>
173
+ ${s ? t`<span class="submenu-indicator" aria-hidden="true">${u}</span>` : n}
174
+ </button>
175
+ `}
176
+ ${s ? t`
177
+ <ul class="submenu ${c ? "is-open" : ""}" role="group">
178
+ ${this._renderItems(e.children, o, i + 1)}
179
+ </ul>
180
+ ` : n}
181
+ </li>
182
+ `;
183
+ })}`;
184
+ }
185
+ _renderMenu(e, n, r) {
186
+ return t`
187
+ <ul class="menu" role="tree" aria-label=${r}>
188
+ ${this._renderItems(e, n, 0)}
189
+ </ul>
190
+ `;
191
+ }
192
+ render() {
193
+ let e = p(this.items, this._searchQuery), r = p(this.footerItems, this._searchQuery);
194
+ return t`
195
+ <div class="logo-wrapper">
196
+ <span class="logo-expanded"><slot name="logo"></slot></span>
197
+ <span class="logo-icon"><slot name="logo-icon"></slot></span>
198
+ </div>
199
+
200
+ ${this.searchable ? t`
201
+ <div class="search-wrapper">
202
+ <span class="search-icon">${d}</span>
203
+ <input
204
+ type="search"
205
+ class="search-input"
206
+ placeholder=${this.searchPlaceholder}
207
+ aria-label="Search navigation"
208
+ .value=${this._searchQuery}
209
+ @input=${this._onSearchInput}
210
+ />
211
+ </div>
212
+ ` : n}
213
+
214
+ <nav
215
+ class="nav-main"
216
+ aria-label="Main"
217
+ @keydown=${this._onNavKeydown}
218
+ >
219
+ ${this._renderMenu(e, "m", "Main navigation")}
220
+ </nav>
221
+
222
+ ${this.footerItems.length > 0 ? t`
223
+ <nav
224
+ class="nav-footer"
225
+ aria-label="Footer"
226
+ @keydown=${this._onNavKeydown}
227
+ >
228
+ ${this._renderMenu(r, "f", "Footer navigation")}
229
+ </nav>
230
+ ` : n}
231
+
232
+ <div class="bottom-slot ${this._bottomSlotPopulated ? "" : "is-empty"}">
233
+ <slot name="bottom" @slotchange=${this._onBottomSlotChange}></slot>
234
+ </div>
235
+ `;
236
+ }
237
+ constructor(...e) {
238
+ super(...e), this.items = [], this.footerItems = [], this.searchable = !1, this.searchPlaceholder = "Search…", this.collapsed = !1, this._openPaths = /* @__PURE__ */ new Set(), this._searchQuery = "", this._hoverExpanded = !1, this._bottomSlotPopulated = !1, this._onBottomSlotChange = (e) => {
239
+ this._bottomSlotPopulated = e.target.assignedNodes({ flatten: !0 }).length > 0;
240
+ }, this._onMouseEnter = () => {
241
+ this.collapsed && (this._hoverExpanded = !0);
242
+ }, this._onMouseLeave = () => {
243
+ this.collapsed && (this._hoverExpanded = !1, this._openPaths = /* @__PURE__ */ new Set());
244
+ };
245
+ }
246
+ };
247
+ l([a({ attribute: !1 })], m.prototype, "items", void 0), l([a({ attribute: !1 })], m.prototype, "footerItems", void 0), l([a({ type: Boolean })], m.prototype, "searchable", void 0), l([a({ type: String })], m.prototype, "searchPlaceholder", void 0), l([a({ attribute: !1 })], m.prototype, "activeValue", void 0), l([a({ type: Boolean })], m.prototype, "collapsed", void 0), l([o()], m.prototype, "_openPaths", void 0), l([o()], m.prototype, "_searchQuery", void 0), l([o()], m.prototype, "_hoverExpanded", void 0), l([o()], m.prototype, "_bottomSlotPopulated", void 0), m = l([i("app-menu")], m);
248
+ export { m as t };
package/dist/menu.js ADDED
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./menu-DmAFaVi5.js";
2
+ export { e as Menu };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Mock data for app-table demos and tests.
3
+ * Use: import { mockTableRows, type MockTableRow } from './mock/table-data'
4
+ */
5
+ export interface MockTableRow {
6
+ id: number;
7
+ name: string;
8
+ department: string;
9
+ role: string;
10
+ salary: number;
11
+ status: 'active' | 'inactive';
12
+ }
13
+ /** Default mock rows for table (42 items). */
14
+ export declare const mockTableRows: MockTableRow[];
15
+ /** Small subset (e.g. for minimal table demos). */
16
+ export declare const mockTableRowsSmall: MockTableRow[];
@@ -0,0 +1,174 @@
1
+ import { LitElement as e, html as t, unsafeCSS as n } from "lit";
2
+ import { customElement as r, property as i, query as a, state as o } from "lit/decorators.js";
3
+ var s = ":host{display:contents}.backdrop{z-index:100;background:var(--modal-backdrop);animation:backdrop-in var(--modal-transition-duration) var(--ease-emphasized-out) forwards;position:fixed;inset:0}@keyframes backdrop-in{0%{opacity:0}to{opacity:1}}.dialog{z-index:101;background:var(--color-surface);border:1px solid var(--color-border);border-radius:var(--modal-border-radius);animation:dialog-in var(--modal-transition-duration) var(--ease-emphasized-out) forwards;outline:none;flex-direction:column;max-height:calc(100dvh - 2rem);display:flex;position:fixed;inset-block-start:50%;inset-inline-start:50%;overflow-y:auto;translate:-50% -50%;box-shadow:0 4px 6px -1px oklch(0% 0 0/.08),0 10px 15px -3px oklch(0% 0 0/.06)}.dialog--sm{width:min(24rem,100vw - 2rem)}.dialog--md{width:min(var(--modal-width), calc(100vw - 2rem))}.dialog--lg{width:min(44rem,100vw - 2rem)}@keyframes dialog-in{0%{opacity:0;scale:.96}to{opacity:1;scale:1}}.header{padding:var(--modal-padding);flex-shrink:0;justify-content:space-between;align-items:center;gap:1rem;padding-block-end:1rem;display:flex}.title{color:var(--color-text);margin:0;font-size:1.125rem;font-weight:600;line-height:1.3}.close-btn{border-radius:var(--radius-button);width:2rem;height:2rem;color:var(--color-text-muted);cursor:pointer;transition:background-color var(--modal-transition-duration) var(--ease-emphasized);background:0 0;border:none;flex-shrink:0;justify-content:center;align-items:center;padding:0;display:inline-flex}.close-btn:hover{background:var(--color-surface-elevated);color:var(--color-text)}.close-btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.description{padding-inline:var(--modal-padding);color:var(--color-text-muted);flex-shrink:0;margin:0;padding-block-end:1rem;font-size:.9375rem;line-height:1.5}.body{padding-inline:var(--modal-padding);flex-direction:column;gap:.75rem;padding-block-end:var(--modal-padding);display:flex;overflow-y:auto}.body:empty{display:none}.body--flush{gap:0;padding:0}.footer{flex-shrink:0}.footer[hidden]{display:none!important}.divider{background:var(--color-border);height:1px}.footer-slot{display:none}.footer-slot--active,.actions{padding:var(--modal-padding);justify-content:flex-end;align-items:center;gap:.5rem;padding-block-start:1rem;display:flex}.actions--center{justify-content:center}.btn{min-width:5rem;min-height:2.5rem;padding:var(--button-padding-block) var(--button-padding-inline);font-size:var(--button-font-size);font-weight:var(--button-font-weight);border-radius:var(--radius-button);cursor:pointer;transition:background-color var(--button-transition-duration) var(--ease-emphasized);border:none;justify-content:center;align-items:center;display:inline-flex}.btn--primary{background:var(--color-primary);color:var(--color-text-inverse)}.btn--primary:hover{background:var(--color-primary-hover)}.btn--ghost{color:var(--color-text-muted);border:1px solid var(--color-border);background:0 0}.btn--ghost:hover{background:var(--color-surface-elevated);color:var(--color-text);border-color:var(--color-border-strong)}.btn:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.sr-only{clip:rect(0 0 0 0);white-space:nowrap;border:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}";
4
+ function c(e, t, n, r) {
5
+ var i = arguments.length, a = i < 3 ? t : r === null ? r = Object.getOwnPropertyDescriptor(t, n) : r, o;
6
+ if (typeof Reflect == "object" && typeof Reflect.decorate == "function") a = Reflect.decorate(e, t, n, r);
7
+ else for (var s = e.length - 1; s >= 0; s--) (o = e[s]) && (a = (i < 3 ? o(a) : i > 3 ? o(t, n, a) : o(t, n)) || a);
8
+ return i > 3 && a && Object.defineProperty(t, n, a), a;
9
+ }
10
+ var l = class extends e {
11
+ static {
12
+ this.styles = [n(s)];
13
+ }
14
+ updated(e) {
15
+ e.has("open") && (this.open ? (this._previousFocus = document.activeElement, requestAnimationFrame(() => this._focusFirst()), document.body.style.overflow = "hidden") : (document.body.style.overflow = "", this._previousFocus?.focus(), this._previousFocus = null));
16
+ }
17
+ connectedCallback() {
18
+ super.connectedCallback(), this.addEventListener("keydown", this._handleKeydown);
19
+ }
20
+ disconnectedCallback() {
21
+ super.disconnectedCallback(), this.removeEventListener("keydown", this._handleKeydown), document.body.style.overflow = "";
22
+ }
23
+ _getFocusable() {
24
+ return this._dialog ? Array.from(this._dialog.querySelectorAll(this._focusableSelectors)) : [];
25
+ }
26
+ _focusFirst() {
27
+ let e = this._getFocusable();
28
+ e.length ? e[0].focus() : this._dialog?.focus();
29
+ }
30
+ _trapFocus(e) {
31
+ let t = this._getFocusable();
32
+ if (!t.length) return;
33
+ let n = t[0], r = t[t.length - 1];
34
+ e.shiftKey ? document.activeElement === n && (e.preventDefault(), r.focus()) : document.activeElement === r && (e.preventDefault(), n.focus());
35
+ }
36
+ _handleBackdropClick(e) {
37
+ this.closeOnBackdrop && e.target === e.currentTarget && this._close();
38
+ }
39
+ _close() {
40
+ this.open = !1, this.dispatchEvent(new CustomEvent("modal-close", {
41
+ bubbles: !0,
42
+ composed: !0
43
+ }));
44
+ }
45
+ _handleConfirm() {
46
+ this.dispatchEvent(new CustomEvent("modal-confirm", {
47
+ bubbles: !0,
48
+ composed: !0
49
+ })), this._close();
50
+ }
51
+ _handleCancel() {
52
+ this.dispatchEvent(new CustomEvent("modal-cancel", {
53
+ bubbles: !0,
54
+ composed: !0
55
+ })), this._close();
56
+ }
57
+ get _resolvedConfirmLabel() {
58
+ return this.confirmLabel ? this.confirmLabel : this.variant === "form" ? "Save" : "Confirm";
59
+ }
60
+ _onFooterSlotChange(e) {
61
+ this._hasFooterContent = e.target.assignedNodes({ flatten: !0 }).length > 0;
62
+ }
63
+ _renderBuiltInActions() {
64
+ return this.variant === "info" ? t`
65
+ <div class="actions actions--center">
66
+ <button type="button" class="btn btn--primary" @click=${this._handleConfirm}>
67
+ ${this.okLabel}
68
+ </button>
69
+ </div>
70
+ ` : t`
71
+ <div class="actions">
72
+ <button type="button" class="btn btn--ghost" @click=${this._handleCancel}>
73
+ ${this.cancelLabel}
74
+ </button>
75
+ <button type="button" class="btn btn--primary" @click=${this._handleConfirm}>
76
+ ${this._resolvedConfirmLabel}
77
+ </button>
78
+ </div>
79
+ `;
80
+ }
81
+ /**
82
+ * Whether the footer area (divider + buttons) should be visible at all.
83
+ * Hidden only when hide-actions=true AND the footer slot has no content.
84
+ */ get _showFooter() {
85
+ return this._hasFooterContent || !this.hideActions;
86
+ }
87
+ render() {
88
+ return this.open ? t`
89
+ <div
90
+ class="backdrop"
91
+ @click=${this._handleBackdropClick}
92
+ aria-hidden="true"
93
+ ></div>
94
+
95
+ <div
96
+ class="dialog dialog--${this.size}"
97
+ role="dialog"
98
+ aria-modal="true"
99
+ aria-labelledby="modal-title"
100
+ aria-describedby=${this.description ? "modal-desc" : ""}
101
+ tabindex="-1"
102
+ >
103
+ <header class="header">
104
+ <h2 class="title" id="modal-title">${this.title}</h2>
105
+ <button
106
+ type="button"
107
+ class="close-btn"
108
+ aria-label="Close dialog"
109
+ @click=${this._close}
110
+ >
111
+ <svg viewBox="0 0 16 16" fill="none" aria-hidden="true" width="16" height="16">
112
+ <path d="M3 3l10 10M13 3L3 13" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/>
113
+ </svg>
114
+ </button>
115
+ </header>
116
+
117
+ ${this.description ? t`
118
+ <p class="description" id="modal-desc">${this.description}</p>
119
+ ` : ""}
120
+
121
+ <div class="body ${this.flush ? "body--flush" : ""}">
122
+ <slot></slot>
123
+ </div>
124
+
125
+ <!--
126
+ Footer slot is always rendered (even when hide-actions) so slotchange
127
+ fires correctly. The outer .footer wrapper hides via [hidden] when
128
+ hide-actions=true AND the slot is empty.
129
+ -->
130
+ <div class="footer" ?hidden=${!this._showFooter}>
131
+ <div class="divider" aria-hidden="true"></div>
132
+ <!-- Custom footer: slot content replaces built-in action buttons -->
133
+ <div class="footer-slot ${this._hasFooterContent ? "footer-slot--active" : ""}">
134
+ <slot name="footer" @slotchange=${this._onFooterSlotChange}></slot>
135
+ </div>
136
+ <!-- Built-in actions: shown only when footer slot is empty -->
137
+ ${this._hasFooterContent ? "" : this._renderBuiltInActions()}
138
+ </div>
139
+ </div>
140
+ ` : t``;
141
+ }
142
+ constructor(...e) {
143
+ super(...e), this.open = !1, this.title = "", this.description = "", this.variant = "info", this.size = "md", this.confirmLabel = "", this.cancelLabel = "Cancel", this.okLabel = "OK", this.closeOnBackdrop = !0, this.hideActions = !1, this.flush = !1, this._hasFooterContent = !1, this._previousFocus = null, this._handleKeydown = (e) => {
144
+ this.open && (e.key === "Escape" && (e.stopPropagation(), this._close()), e.key === "Tab" && this._trapFocus(e));
145
+ }, this._focusableSelectors = [
146
+ "button:not([disabled])",
147
+ "[href]",
148
+ "input:not([disabled])",
149
+ "select:not([disabled])",
150
+ "textarea:not([disabled])",
151
+ "[tabindex]:not([tabindex=\"-1\"])"
152
+ ].join(", ");
153
+ }
154
+ };
155
+ c([i({
156
+ type: Boolean,
157
+ reflect: !0
158
+ })], l.prototype, "open", void 0), c([i({ type: String })], l.prototype, "title", void 0), c([i({ type: String })], l.prototype, "description", void 0), c([i({ type: String })], l.prototype, "variant", void 0), c([i({ type: String })], l.prototype, "size", void 0), c([i({
159
+ type: String,
160
+ attribute: "confirm-label"
161
+ })], l.prototype, "confirmLabel", void 0), c([i({
162
+ type: String,
163
+ attribute: "cancel-label"
164
+ })], l.prototype, "cancelLabel", void 0), c([i({
165
+ type: String,
166
+ attribute: "ok-label"
167
+ })], l.prototype, "okLabel", void 0), c([i({
168
+ type: Boolean,
169
+ attribute: "close-on-backdrop"
170
+ })], l.prototype, "closeOnBackdrop", void 0), c([i({
171
+ type: Boolean,
172
+ attribute: "hide-actions"
173
+ })], l.prototype, "hideActions", void 0), c([i({ type: Boolean })], l.prototype, "flush", void 0), c([o()], l.prototype, "_hasFooterContent", void 0), c([a(".dialog")], l.prototype, "_dialog", void 0), l = c([r("app-modal")], l);
174
+ export { l as t };
package/dist/modal.js ADDED
@@ -0,0 +1,2 @@
1
+ import { t as e } from "./modal-v1GlqMF_.js";
2
+ export { e as Modal };
@@ -0,0 +1,2 @@
1
+ import { Button as ButtonElement } from '../components/button/button.ts';
2
+ export declare const Button: import('@lit/react').ReactWebComponent<ButtonElement, {}>;
@@ -0,0 +1,9 @@
1
+ import { t as e } from "../button-DYrT530y.js";
2
+ import * as t from "react";
3
+ import { createComponent as n } from "@lit/react";
4
+ const r = n({
5
+ tagName: "app-button",
6
+ elementClass: e,
7
+ react: t
8
+ });
9
+ export { r as Button };
@@ -0,0 +1,6 @@
1
+ import { EventName } from '@lit/react';
2
+ import { DropdownButton as DropdownButtonElement } from '../components/dropdown-button/dropdown-button.ts';
3
+ import { DropdownSelectEventDetail } from '../components/dropdown-button/dropdown-button-types.ts';
4
+ export declare const DropdownButton: import('@lit/react').ReactWebComponent<DropdownButtonElement, {
5
+ onDropdownSelect: EventName<CustomEvent<DropdownSelectEventDetail>>;
6
+ }>;
@@ -0,0 +1,10 @@
1
+ import { t as e } from "../dropdown-button-B6XNoy4L.js";
2
+ import * as t from "react";
3
+ import { createComponent as n } from "@lit/react";
4
+ const r = n({
5
+ tagName: "app-dropdown-button",
6
+ elementClass: e,
7
+ react: t,
8
+ events: { onDropdownSelect: "dropdown-select" }
9
+ });
10
+ export { r as DropdownButton };
@@ -0,0 +1,8 @@
1
+ import { EventName } from '@lit/react';
2
+ import { FormLayout as FormLayoutElement } from '../components/layouts/form/form-layout.ts';
3
+ import { FormLayoutStageEventDetail } from '../components/layouts/form/form-layout-types.ts';
4
+ export declare const FormLayout: import('@lit/react').ReactWebComponent<FormLayoutElement, {
5
+ onFormLayoutNext: EventName<CustomEvent<FormLayoutStageEventDetail>>;
6
+ onFormLayoutBack: EventName<CustomEvent<FormLayoutStageEventDetail>>;
7
+ onFormLayoutSubmit: EventName<CustomEvent<FormLayoutStageEventDetail>>;
8
+ }>;
@@ -0,0 +1,14 @@
1
+ import { t as e } from "../form-layout-DCX8X-8-.js";
2
+ import * as t from "react";
3
+ import { createComponent as n } from "@lit/react";
4
+ const r = n({
5
+ tagName: "app-form-layout",
6
+ elementClass: e,
7
+ react: t,
8
+ events: {
9
+ onFormLayoutNext: "form-layout-next",
10
+ onFormLayoutBack: "form-layout-back",
11
+ onFormLayoutSubmit: "form-layout-submit"
12
+ }
13
+ });
14
+ export { r as FormLayout };
@@ -0,0 +1,21 @@
1
+ export { Button } from './button.ts';
2
+ export { DropdownButton } from './dropdown-button.ts';
3
+ export { Input } from './input.ts';
4
+ export { Menu } from './menu.ts';
5
+ export { Modal } from './modal.ts';
6
+ export { Selector } from './selector.ts';
7
+ export { Table } from './table.ts';
8
+ export { Tabs } from './tabs.ts';
9
+ export { Toggle } from './toggle.ts';
10
+ export { FormLayout } from './form-layout.ts';
11
+ export { Layout } from './layout.ts';
12
+ export type { ButtonIconPosition, ButtonType } from '../components/button/button-types.ts';
13
+ export type { DropdownItem, DropdownSelectEventDetail, DropdownPlacement } from '../components/dropdown-button/dropdown-button-types.ts';
14
+ export type { InputType, InputState } from '../components/input/input-types.ts';
15
+ export type { MenuItem, MenuSelectEventDetail, MenuSearchEventDetail } from '../components/menu/menu-types.ts';
16
+ export type { ModalVariant, ModalSize } from '../components/modal/modal-types.ts';
17
+ export type { SelectorOption, SelectorGroup, SelectorChangeEventDetail, SelectorState } from '../components/selector/selector-types.ts';
18
+ export type { ColumnDef, SortDir, TableSortEvent, TablePageEvent, TableColumnToggleEvent } from '../components/table/table-types.ts';
19
+ export type { TabItem, TabChangeEventDetail } from '../components/tabs/tabs.ts';
20
+ export type { ToggleIconPosition, ToggleChangeEventDetail } from '../components/toggle/toggle-types.ts';
21
+ export type { FormLayoutStageEventDetail } from '../components/layouts/form/form-layout-types.ts';
@@ -0,0 +1,2 @@
1
+ import { Input as InputElement } from '../components/input/input.ts';
2
+ export declare const Input: import('@lit/react').ReactWebComponent<InputElement, {}>;
@@ -0,0 +1,9 @@
1
+ import { t as e } from "../input-BVlPYqTe.js";
2
+ import * as t from "react";
3
+ import { createComponent as n } from "@lit/react";
4
+ const r = n({
5
+ tagName: "app-input",
6
+ elementClass: e,
7
+ react: t
8
+ });
9
+ export { r as Input };
@@ -0,0 +1,2 @@
1
+ import { Layout as LayoutElement } from '../components/layouts/page/layout.ts';
2
+ export declare const Layout: import('@lit/react').ReactWebComponent<LayoutElement, {}>;
@@ -0,0 +1,9 @@
1
+ import { t as e } from "../layout-CYvgu_WE.js";
2
+ import * as t from "react";
3
+ import { createComponent as n } from "@lit/react";
4
+ const r = n({
5
+ tagName: "app-layout",
6
+ elementClass: e,
7
+ react: t
8
+ });
9
+ export { r as Layout };
@@ -0,0 +1,7 @@
1
+ import { EventName } from '@lit/react';
2
+ import { Menu as MenuElement } from '../components/menu/menu.ts';
3
+ import { MenuSelectEventDetail, MenuSearchEventDetail } from '../components/menu/menu-types.ts';
4
+ export declare const Menu: import('@lit/react').ReactWebComponent<MenuElement, {
5
+ onMenuSelect: EventName<CustomEvent<MenuSelectEventDetail>>;
6
+ onMenuSearch: EventName<CustomEvent<MenuSearchEventDetail>>;
7
+ }>;
@@ -0,0 +1,13 @@
1
+ import { t as e } from "../menu-DmAFaVi5.js";
2
+ import * as t from "react";
3
+ import { createComponent as n } from "@lit/react";
4
+ const r = n({
5
+ tagName: "app-menu",
6
+ elementClass: e,
7
+ react: t,
8
+ events: {
9
+ onMenuSelect: "menu-select",
10
+ onMenuSearch: "menu-search"
11
+ }
12
+ });
13
+ export { r as Menu };
@@ -0,0 +1,7 @@
1
+ import { EventName } from '@lit/react';
2
+ import { Modal as ModalElement } from '../components/modal/modal.ts';
3
+ export declare const Modal: import('@lit/react').ReactWebComponent<ModalElement, {
4
+ onModalConfirm: EventName<CustomEvent>;
5
+ onModalCancel: EventName<CustomEvent>;
6
+ onModalClose: EventName<CustomEvent>;
7
+ }>;
@@ -0,0 +1,14 @@
1
+ import { t as e } from "../modal-v1GlqMF_.js";
2
+ import * as t from "react";
3
+ import { createComponent as n } from "@lit/react";
4
+ const r = n({
5
+ tagName: "app-modal",
6
+ elementClass: e,
7
+ react: t,
8
+ events: {
9
+ onModalConfirm: "modal-confirm",
10
+ onModalCancel: "modal-cancel",
11
+ onModalClose: "modal-close"
12
+ }
13
+ });
14
+ export { r as Modal };
@@ -0,0 +1,6 @@
1
+ import { EventName } from '@lit/react';
2
+ import { Selector as SelectorElement } from '../components/selector/selector.ts';
3
+ import { SelectorChangeEventDetail } from '../components/selector/selector-types.ts';
4
+ export declare const Selector: import('@lit/react').ReactWebComponent<SelectorElement, {
5
+ onSelectorChange: EventName<CustomEvent<SelectorChangeEventDetail>>;
6
+ }>;
@@ -0,0 +1,10 @@
1
+ import { t as e } from "../selector-Bl7Nbkqo.js";
2
+ import * as t from "react";
3
+ import { createComponent as n } from "@lit/react";
4
+ const r = n({
5
+ tagName: "app-selector",
6
+ elementClass: e,
7
+ react: t,
8
+ events: { onSelectorChange: "selector-change" }
9
+ });
10
+ export { r as Selector };
@@ -0,0 +1,8 @@
1
+ import { EventName } from '@lit/react';
2
+ import { Table as TableElement } from '../components/table/table.ts';
3
+ import { TableSortEvent, TablePageEvent, TableColumnToggleEvent } from '../components/table/table-types.ts';
4
+ export declare const Table: import('@lit/react').ReactWebComponent<TableElement, {
5
+ onTableSort: EventName<CustomEvent<TableSortEvent>>;
6
+ onTablePage: EventName<CustomEvent<TablePageEvent>>;
7
+ onTableColumnToggle: EventName<CustomEvent<TableColumnToggleEvent>>;
8
+ }>;