scb-wc-test 0.1.1

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 (178) hide show
  1. package/README.md +130 -0
  2. package/all.js +54 -0
  3. package/dummy.png +0 -0
  4. package/index.d.ts +54 -0
  5. package/index.js +108 -0
  6. package/mvc/components/all.js +53 -0
  7. package/mvc/components/scb-accordion/scb-accordion-item.js +194 -0
  8. package/mvc/components/scb-accordion/scb-accordion.js +5 -0
  9. package/mvc/components/scb-app-bar/scb-app-bar.js +144 -0
  10. package/mvc/components/scb-avatar/scb-avatar.js +99 -0
  11. package/mvc/components/scb-breadcrumb/scb-breadcrumb-item.js +17 -0
  12. package/mvc/components/scb-breadcrumb/scb-breadcrumb.js +52 -0
  13. package/mvc/components/scb-button/scb-button.js +121 -0
  14. package/mvc/components/scb-calendar-card/scb-calendar-card.js +140 -0
  15. package/mvc/components/scb-card/scb-card.js +256 -0
  16. package/mvc/components/scb-checkbox/scb-checkbox-group.js +33 -0
  17. package/mvc/components/scb-checkbox/scb-checkbox.js +99 -0
  18. package/mvc/components/scb-chips/scb-chip.js +46 -0
  19. package/mvc/components/scb-dialog/scb-dialog.js +158 -0
  20. package/mvc/components/scb-divider/scb-divider.js +53 -0
  21. package/mvc/components/scb-drawer/scb-drawer-item.js +114 -0
  22. package/mvc/components/scb-drawer/scb-drawer-section.js +19 -0
  23. package/mvc/components/scb-drawer/scb-drawer.js +79 -0
  24. package/mvc/components/scb-drawer/scb-sub-drawer.js +10 -0
  25. package/mvc/components/scb-fact-card/scb-fact-card-content.js +44 -0
  26. package/mvc/components/scb-fact-card/scb-fact-card.js +66 -0
  27. package/mvc/components/scb-footer/scb-footer-section.js +3 -0
  28. package/mvc/components/scb-footer/scb-footer.js +205 -0
  29. package/mvc/components/scb-grid/scb-grid-item.js +9 -0
  30. package/mvc/components/scb-grid/scb-grid.js +81 -0
  31. package/mvc/components/scb-grid/scb-stack.js +16 -0
  32. package/mvc/components/scb-header/scb-header-drawer-group.js +1 -0
  33. package/mvc/components/scb-header/scb-header-drawer-item.js +1 -0
  34. package/mvc/components/scb-header/scb-header-tab.js +1 -0
  35. package/mvc/components/scb-header/scb-header-utility.js +1 -0
  36. package/mvc/components/scb-header/scb-header.js +240 -0
  37. package/mvc/components/scb-icon-button/scb-icon-button.js +95 -0
  38. package/mvc/components/scb-keyfigure-card/scb-keyfigure-card.js +69 -0
  39. package/mvc/components/scb-link/scb-link.js +31 -0
  40. package/mvc/components/scb-list/scb-list-item.js +38 -0
  41. package/mvc/components/scb-list/scb-list.js +10 -0
  42. package/mvc/components/scb-menu/scb-menu-item.js +44 -0
  43. package/mvc/components/scb-menu/scb-menu.js +17 -0
  44. package/mvc/components/scb-menu/scb-sub-menu.js +29 -0
  45. package/mvc/components/scb-notification/scb-notification.js +120 -0
  46. package/mvc/components/scb-progress-indicator/scb-progress-indicator.js +84 -0
  47. package/mvc/components/scb-radio-button/scb-radio-button.js +95 -0
  48. package/mvc/components/scb-radio-button/scb-radio-group.js +28 -0
  49. package/mvc/components/scb-search/scb-search.js +211 -0
  50. package/mvc/components/scb-snackbar/scb-snackbar.js +83 -0
  51. package/mvc/components/scb-status-pill/scb-status-pill.js +31 -0
  52. package/mvc/components/scb-switch/scb-switch.js +54 -0
  53. package/mvc/components/scb-tabs/scb-primary-tab.js +7 -0
  54. package/mvc/components/scb-tabs/scb-secondary-tab.js +7 -0
  55. package/mvc/components/scb-tabs/scb-tabs.js +23 -0
  56. package/mvc/components/scb-textfield/scb-textfield.js +135 -0
  57. package/mvc/components/scb-toc/scb-toc-item.js +84 -0
  58. package/mvc/components/scb-toc/scb-toc.js +6 -0
  59. package/mvc/components/scb-tooltip/scb-tooltip.js +216 -0
  60. package/mvc/scb-logo.svg +21 -0
  61. package/mvc/scb-wc-test.css +1 -0
  62. package/mvc/scb.svg +14 -0
  63. package/mvc/vendor/preload-helper.js +1 -0
  64. package/mvc/vendor/vendor-lit.js +1 -0
  65. package/mvc/vendor/vendor-material.js +764 -0
  66. package/mvc/vendor/vendor.js +68 -0
  67. package/package.json +248 -0
  68. package/scb-accordion/scb-accordion-item.d.ts +37 -0
  69. package/scb-accordion/scb-accordion-item.js +343 -0
  70. package/scb-accordion/scb-accordion.d.ts +6 -0
  71. package/scb-accordion/scb-accordion.js +33 -0
  72. package/scb-app-bar/scb-app-bar.d.ts +10 -0
  73. package/scb-app-bar/scb-app-bar.js +192 -0
  74. package/scb-avatar/scb-avatar.d.ts +30 -0
  75. package/scb-avatar/scb-avatar.js +169 -0
  76. package/scb-breadcrumb/scb-breadcrumb-item.d.ts +9 -0
  77. package/scb-breadcrumb/scb-breadcrumb-item.js +54 -0
  78. package/scb-breadcrumb/scb-breadcrumb.d.ts +16 -0
  79. package/scb-breadcrumb/scb-breadcrumb.js +105 -0
  80. package/scb-button/scb-button.d.ts +26 -0
  81. package/scb-button/scb-button.js +247 -0
  82. package/scb-calendar-card/scb-calendar-card.d.ts +20 -0
  83. package/scb-calendar-card/scb-calendar-card.js +191 -0
  84. package/scb-card/scb-card.d.ts +24 -0
  85. package/scb-card/scb-card.js +345 -0
  86. package/scb-checkbox/scb-checkbox-group.d.ts +17 -0
  87. package/scb-checkbox/scb-checkbox-group.js +80 -0
  88. package/scb-checkbox/scb-checkbox.d.ts +20 -0
  89. package/scb-checkbox/scb-checkbox.js +157 -0
  90. package/scb-chips/scb-chip.d.ts +24 -0
  91. package/scb-chips/scb-chip.js +150 -0
  92. package/scb-dialog/scb-dialog.d.ts +58 -0
  93. package/scb-dialog/scb-dialog.js +390 -0
  94. package/scb-divider/scb-divider.d.ts +9 -0
  95. package/scb-divider/scb-divider.js +85 -0
  96. package/scb-drawer/scb-drawer-item.d.ts +61 -0
  97. package/scb-drawer/scb-drawer-item.js +220 -0
  98. package/scb-drawer/scb-drawer-section.d.ts +7 -0
  99. package/scb-drawer/scb-drawer-section.js +44 -0
  100. package/scb-drawer/scb-drawer.d.ts +97 -0
  101. package/scb-drawer/scb-drawer.js +258 -0
  102. package/scb-drawer/scb-sub-drawer.d.ts +10 -0
  103. package/scb-drawer/scb-sub-drawer.js +43 -0
  104. package/scb-fact-card/scb-fact-card-content.d.ts +10 -0
  105. package/scb-fact-card/scb-fact-card-content.js +83 -0
  106. package/scb-fact-card/scb-fact-card.d.ts +15 -0
  107. package/scb-fact-card/scb-fact-card.js +110 -0
  108. package/scb-footer/scb-footer-section.d.ts +21 -0
  109. package/scb-footer/scb-footer-section.js +28 -0
  110. package/scb-footer/scb-footer.d.ts +27 -0
  111. package/scb-footer/scb-footer.js +326 -0
  112. package/scb-grid/scb-grid-item.d.ts +28 -0
  113. package/scb-grid/scb-grid-item.js +66 -0
  114. package/scb-grid/scb-grid.d.ts +33 -0
  115. package/scb-grid/scb-grid.js +152 -0
  116. package/scb-grid/scb-stack.d.ts +29 -0
  117. package/scb-grid/scb-stack.js +82 -0
  118. package/scb-header/scb-header-drawer-group.d.ts +13 -0
  119. package/scb-header/scb-header-drawer-group.js +28 -0
  120. package/scb-header/scb-header-drawer-item.d.ts +14 -0
  121. package/scb-header/scb-header-drawer-item.js +31 -0
  122. package/scb-header/scb-header-tab.d.ts +13 -0
  123. package/scb-header/scb-header-tab.js +28 -0
  124. package/scb-header/scb-header-utility.d.ts +14 -0
  125. package/scb-header/scb-header-utility.js +31 -0
  126. package/scb-header/scb-header.d.ts +105 -0
  127. package/scb-header/scb-header.js +618 -0
  128. package/scb-icon-button/scb-icon-button.d.ts +31 -0
  129. package/scb-icon-button/scb-icon-button.js +208 -0
  130. package/scb-keyfigure-card/scb-keyfigure-card.d.ts +13 -0
  131. package/scb-keyfigure-card/scb-keyfigure-card.js +119 -0
  132. package/scb-link/scb-link.d.ts +17 -0
  133. package/scb-link/scb-link.js +74 -0
  134. package/scb-list/scb-list-item.d.ts +32 -0
  135. package/scb-list/scb-list-item.js +144 -0
  136. package/scb-list/scb-list.d.ts +8 -0
  137. package/scb-list/scb-list.js +39 -0
  138. package/scb-logo.svg +21 -0
  139. package/scb-menu/scb-menu-item.d.ts +22 -0
  140. package/scb-menu/scb-menu-item.js +107 -0
  141. package/scb-menu/scb-menu.d.ts +21 -0
  142. package/scb-menu/scb-menu.js +98 -0
  143. package/scb-menu/scb-sub-menu.d.ts +12 -0
  144. package/scb-menu/scb-sub-menu.js +69 -0
  145. package/scb-notification/scb-notification.d.ts +16 -0
  146. package/scb-notification/scb-notification.js +187 -0
  147. package/scb-progress-indicator/scb-progress-indicator.d.ts +11 -0
  148. package/scb-progress-indicator/scb-progress-indicator.js +122 -0
  149. package/scb-radio-button/scb-radio-button.d.ts +19 -0
  150. package/scb-radio-button/scb-radio-button.js +176 -0
  151. package/scb-radio-button/scb-radio-group.d.ts +20 -0
  152. package/scb-radio-button/scb-radio-group.js +81 -0
  153. package/scb-search/scb-search.d.ts +45 -0
  154. package/scb-search/scb-search.js +410 -0
  155. package/scb-snackbar/scb-snackbar.d.ts +17 -0
  156. package/scb-snackbar/scb-snackbar.js +140 -0
  157. package/scb-status-pill/scb-status-pill.d.ts +9 -0
  158. package/scb-status-pill/scb-status-pill.js +62 -0
  159. package/scb-switch/scb-switch.d.ts +21 -0
  160. package/scb-switch/scb-switch.js +111 -0
  161. package/scb-tabs/scb-primary-tab.d.ts +17 -0
  162. package/scb-tabs/scb-primary-tab.js +93 -0
  163. package/scb-tabs/scb-secondary-tab.d.ts +17 -0
  164. package/scb-tabs/scb-secondary-tab.js +97 -0
  165. package/scb-tabs/scb-tabs.d.ts +10 -0
  166. package/scb-tabs/scb-tabs.js +66 -0
  167. package/scb-textfield/scb-textfield.d.ts +41 -0
  168. package/scb-textfield/scb-textfield.js +258 -0
  169. package/scb-toc/scb-toc-item.d.ts +21 -0
  170. package/scb-toc/scb-toc-item.js +196 -0
  171. package/scb-toc/scb-toc.d.ts +6 -0
  172. package/scb-toc/scb-toc.js +27 -0
  173. package/scb-tooltip/scb-tooltip.d.ts +32 -0
  174. package/scb-tooltip/scb-tooltip.js +329 -0
  175. package/scb-wc-test.bundle.js +5429 -0
  176. package/scb-wc-test.css +1 -0
  177. package/scb-wc-test.d.ts +106 -0
  178. package/scb.svg +14 -0
@@ -0,0 +1,220 @@
1
+ import { css as _, LitElement as x, html as d } from "lit";
2
+ import { property as c, state as g, customElement as w } from "lit/decorators.js";
3
+ var y = Object.defineProperty, v = Object.getOwnPropertyDescriptor, i = (e, t, o, a) => {
4
+ for (var n = a > 1 ? void 0 : a ? v(t, o) : t, r = e.length - 1, l; r >= 0; r--)
5
+ (l = e[r]) && (n = (a ? l(t, o, n) : l(n)) || n);
6
+ return a && n && y(t, o, n), n;
7
+ };
8
+ let s = class extends x {
9
+ constructor() {
10
+ super(...arguments), this.label = "", this.selected = !1, this.leadingIcon = "", this.itemHref = "", this.hasSlotContent = !1, this.expanded = !1, this.__submenuId = `sub-${Math.random().toString(36).slice(2)}`, this._toggleExpand = (e) => {
11
+ e && e.stopPropagation(), this.hasSlotContent && (this.expanded = !this.expanded);
12
+ }, this._onButtonClick = (e) => {
13
+ e.stopPropagation(), this._dispatchSelect(), this._toggleExpand();
14
+ }, this._onLinkClick = () => {
15
+ this._dispatchSelect();
16
+ }, this._onKeyDown = (e) => {
17
+ var a, n, r, l, h, b, u, m, f;
18
+ const t = Array.from(
19
+ ((a = this.parentElement) == null ? void 0 : a.querySelectorAll("scb-drawer-item")) || []
20
+ ), o = t.indexOf(this);
21
+ switch (e.key) {
22
+ case "ArrowDown": {
23
+ e.preventDefault(), (r = (n = (t[o + 1] || t[0]).shadowRoot) == null ? void 0 : n.querySelector(".scb-drawer-label-text")) == null || r.focus();
24
+ break;
25
+ }
26
+ case "ArrowUp": {
27
+ e.preventDefault(), (h = (l = (t[o - 1] || t[t.length - 1]).shadowRoot) == null ? void 0 : l.querySelector(".scb-drawer-label-text")) == null || h.focus();
28
+ break;
29
+ }
30
+ case "Home": {
31
+ e.preventDefault(), (u = (b = t[0].shadowRoot) == null ? void 0 : b.querySelector(".scb-drawer-label-text")) == null || u.focus();
32
+ break;
33
+ }
34
+ case "End": {
35
+ e.preventDefault(), (f = (m = t[t.length - 1].shadowRoot) == null ? void 0 : m.querySelector(".scb-drawer-label-text")) == null || f.focus();
36
+ break;
37
+ }
38
+ }
39
+ };
40
+ }
41
+ // scb-icon-button laddas endast när undermeny finns
42
+ /** Ladda alltid md-ripple, md-icon bara om leadingIcon används. */
43
+ async __ensureDepsLoaded() {
44
+ s.__rippleLoaded || (await import("@material/web/ripple/ripple.js"), s.__rippleLoaded = !0), this.leadingIcon && !s.__iconLoaded && (await import("@material/web/icon/icon.js"), s.__iconLoaded = !0), this.hasSlotContent && !s.__iconButtonLoaded && (await import("../scb-icon-button/scb-icon-button.js"), s.__iconButtonLoaded = !0);
45
+ }
46
+ /** Håll koll på att slotten endast innehåller <scb-sub-drawer>. */
47
+ _onSlotChange(e) {
48
+ const o = e.target.assignedElements({ flatten: !0 });
49
+ this.hasSlotContent = o.length > 0 && o.every((a) => a.tagName === "SCB-SUB-DRAWER");
50
+ }
51
+ /** Skicka ”val”-event uppåt så att <scb-drawer> kan markera selected. */
52
+ _dispatchSelect() {
53
+ this.dispatchEvent(
54
+ new CustomEvent("scb-drawer-select", {
55
+ bubbles: !0,
56
+ composed: !0,
57
+ detail: { item: this }
58
+ })
59
+ );
60
+ }
61
+ /** Vid initiering, kolla slotten och lazy-loada depemdencies. */
62
+ async firstUpdated() {
63
+ const e = this.renderRoot.querySelector("slot");
64
+ if (e) {
65
+ const t = e.assignedElements({ flatten: !0 });
66
+ this.hasSlotContent = t.length > 0 && t.every((o) => o.tagName === "SCB-SUB-DRAWER");
67
+ }
68
+ await this.__ensureDepsLoaded();
69
+ }
70
+ /** Om leadingIcon sätts i efterhand, se till att md-icon finns. */
71
+ updated(e) {
72
+ e.has("leadingIcon") && this.leadingIcon && this.__ensureDepsLoaded(), e.has("hasSlotContent") && this.hasSlotContent && this.__ensureDepsLoaded();
73
+ }
74
+ render() {
75
+ const e = !!this.leadingIcon, t = !!this.itemHref, o = this.hasSlotContent;
76
+ return d`
77
+ <div class="scb-drawer-item">
78
+ <div class="scb-drawer-item-label" ?selected=${this.selected}>
79
+ ${t ? d`
80
+ <a
81
+ class="scb-drawer-label-text"
82
+ aria-label="${this.label}"
83
+ href="${this.itemHref}"
84
+ aria-current=${this.selected ? "page" : void 0}
85
+ @click=${this._onLinkClick}
86
+ @keydown=${this._onKeyDown}
87
+ >
88
+ <span class="scb-drawer-click ${e ? "has-icon" : ""}">
89
+ <md-ripple></md-ripple>
90
+ ${e ? d`<md-icon>${this.leadingIcon}</md-icon>` : ""}
91
+ ${this.label}
92
+ </span>
93
+ </a>
94
+ ` : d`
95
+ <button
96
+ type="button"
97
+ class="scb-drawer-label-text"
98
+ @click=${this._onButtonClick}
99
+ @keydown=${this._onKeyDown}
100
+ ${o ? "aria-expanded=" + String(this.expanded) : ""}
101
+ ${o ? "aria-controls=" + this.__submenuId : ""}
102
+ >
103
+ <span class="scb-drawer-click ${e ? "has-icon" : ""}">
104
+ <md-ripple></md-ripple>
105
+ ${e ? d`<md-icon>${this.leadingIcon}</md-icon>` : ""}
106
+ ${this.label}
107
+ </span>
108
+ </button>
109
+ `}
110
+
111
+ ${o ? d`
112
+ <!-- Separat ikonknapp: presentational + ej tabbbar, ingen ARIA-state -->
113
+ <scb-icon-button
114
+ icon="${this.expanded ? "expand_less" : "expand_more"}"
115
+ role="presentation"
116
+ tabindex="-1"
117
+ @click=${(a) => {
118
+ a.stopPropagation(), this._toggleExpand(a);
119
+ }}
120
+ ></scb-icon-button>
121
+ ` : ""}
122
+ </div>
123
+
124
+ <div id="${this.__submenuId}" class="submenu ${this.expanded ? "expanded" : ""}">
125
+ <slot @slotchange=${this._onSlotChange}></slot>
126
+ </div>
127
+ </div>
128
+ `;
129
+ }
130
+ };
131
+ s.__rippleLoaded = !1;
132
+ s.__iconLoaded = !1;
133
+ s.__iconButtonLoaded = !1;
134
+ s.styles = _`
135
+ .scb-drawer-item-label {
136
+ display: flex;
137
+ align-items: center;
138
+ position: relative;
139
+ }
140
+
141
+ .scb-drawer-label-text {
142
+ width: 100%;
143
+ display: block;
144
+ background: transparent;
145
+ border: 0;
146
+ text-align: left;
147
+ font: inherit;
148
+ color: inherit;
149
+ text-decoration: none;
150
+ cursor: pointer;
151
+ padding: 0;
152
+ margin: 0;
153
+ appearance: none;
154
+ -webkit-appearance: none;
155
+ box-sizing: border-box;
156
+ }
157
+
158
+ .scb-drawer-label-text:focus-visible {
159
+ outline: 2px solid var(--md-focus-ring-color, var(--p-40));
160
+ outline-offset: 2px;
161
+ border-radius: 28px;
162
+ box-shadow: none;
163
+ }
164
+
165
+ .scb-drawer-click {
166
+ display: flex;
167
+ align-items: center;
168
+ gap: 12px;
169
+ padding: 14px 20px;
170
+ border-radius: 28px;
171
+ position: relative;
172
+ overflow: hidden;
173
+ color: var(--md-sys-color-on-surface);
174
+ }
175
+ .scb-drawer-click.has-icon { padding: 14px 12px; }
176
+
177
+ .scb-drawer-item-label[selected] .scb-drawer-click,
178
+ :host([selected]) .scb-drawer-click {
179
+ color: var(--md-sys-color-on-secondary-container);
180
+ background: var(--md-sys-color-secondary-container);
181
+ font-weight: 600;
182
+ }
183
+
184
+ scb-icon-button {
185
+ margin-left: auto;
186
+ flex: 0 0 auto;
187
+ }
188
+ .submenu {
189
+ display: none;
190
+ padding-left: 16px;
191
+ }
192
+ .submenu.expanded {
193
+ display: block;
194
+ padding-left: 16px;
195
+ }
196
+ `;
197
+ i([
198
+ c({ type: String })
199
+ ], s.prototype, "label", 2);
200
+ i([
201
+ c({ type: Boolean, reflect: !0 })
202
+ ], s.prototype, "selected", 2);
203
+ i([
204
+ c({ type: String, attribute: "leading-icon" })
205
+ ], s.prototype, "leadingIcon", 2);
206
+ i([
207
+ c({ type: String, attribute: "item-href" })
208
+ ], s.prototype, "itemHref", 2);
209
+ i([
210
+ g()
211
+ ], s.prototype, "hasSlotContent", 2);
212
+ i([
213
+ g()
214
+ ], s.prototype, "expanded", 2);
215
+ s = i([
216
+ w("scb-drawer-item")
217
+ ], s);
218
+ export {
219
+ s as ScbDrawerItem
220
+ };
@@ -0,0 +1,7 @@
1
+ import { LitElement, TemplateResult } from 'lit';
2
+
3
+ export declare class ScbDrawerSection extends LitElement {
4
+ label: string;
5
+ static styles: import('lit').CSSResult;
6
+ render(): TemplateResult;
7
+ }
@@ -0,0 +1,44 @@
1
+ import { css as d, LitElement as n, html as p } from "lit";
2
+ import { property as b, customElement as v } from "lit/decorators.js";
3
+ import "../scb-divider/scb-divider.js";
4
+ var m = Object.defineProperty, f = Object.getOwnPropertyDescriptor, a = (o, e, i, s) => {
5
+ for (var r = s > 1 ? void 0 : s ? f(e, i) : e, c = o.length - 1, l; c >= 0; c--)
6
+ (l = o[c]) && (r = (s ? l(e, i, r) : l(r)) || r);
7
+ return s && r && m(e, i, r), r;
8
+ };
9
+ let t = class extends n {
10
+ constructor() {
11
+ super(...arguments), this.label = "";
12
+ }
13
+ render() {
14
+ return p`
15
+
16
+ <scb-divider></scb-divider>
17
+ ${this.label ? p`
18
+ <div class="scb-drawer-section">
19
+ <div class="scb-drawer-label">${this.label}</div>
20
+ </div>` : ""}
21
+ `;
22
+ }
23
+ };
24
+ t.styles = d`
25
+ .scb-drawer-section {
26
+ display: block;
27
+ width: 100%;
28
+ padding: 14px 12px;
29
+ color: var(--md-sys-color-on-surface);
30
+ font-weight: 600;
31
+ }
32
+ scb-divider {
33
+ margin: 4px 12px;
34
+ }
35
+ `;
36
+ a([
37
+ b({ type: String })
38
+ ], t.prototype, "label", 2);
39
+ t = a([
40
+ v("scb-drawer-section")
41
+ ], t);
42
+ export {
43
+ t as ScbDrawerSection
44
+ };
@@ -0,0 +1,97 @@
1
+ import { LitElement, TemplateResult } from 'lit';
2
+
3
+ /**
4
+
5
+ <scb-drawer>
6
+
7
+ Sidomeny som kan vara static eller floating.
8
+ Kontroll/styrning
9
+ — Triggers i DOM:
10
+ • aria-controls="<drawer-id>" växlar mellan öppet och stängt; aria-expanded uppdateras automatiskt på samma element.
11
+ • data-drawer-open|close|toggle="<drawer-id>" öppnar/stänger/växlar explicit. aria-expanded uppdateras inte; lägg även aria-controls om state ska speglas.
12
+ • Triggers hittas via event.composedPath() och fungerar även över shadow DOM; om båda attributtyperna används på samma element prioriteras data-drawer-*.
13
+ — Programmatiskt: element.open = true|false (alla side effects hanteras: overlay, scroll-lås, fokus, events).
14
+ Overlay
15
+ — Aktiveras med overlay och ritas som global scrim på document.body.
16
+ — Klick på overlay stänger om close-on-overlay är satt (default: true).
17
+ — lock-scroll låser <html> och <body> medan drawern är öppen.
18
+ — Klick utanför drawern stänger komponenten. Utan overlay: klick utanför själva drawern. Med overlay: klick på overlay (styrt av close-on-overlay).
19
+ Fokus & tangentbord
20
+ — ESC stänger.
21
+ — I overlay-läge finns en enkel focus trap (Tab/Shift+Tab).
22
+ — Fokus återställs till senaste trigger när drawern stängs.
23
+ Modal
24
+ — modal sätter role="dialog" och aria-modal="true".
25
+ Händelser
26
+ — "scb-drawer-opened" och "scb-drawer-closed" bubblar vid state-ändring.
27
+ CSS-variabler
28
+ — --scb-drawer-z, --scb-drawer-overlay-z, --scb-drawer-overlay-color (kanske ska vi sätta dem globalt? Får klura på det).
29
+ */
30
+ export declare class ScbDrawer extends LitElement {
31
+ /** Rubrik i headern. */
32
+ label: string;
33
+ /** Underrubrik i headern (attribute: sub-label). */
34
+ subLabel: string;
35
+ /** floating (fixed) drawer med tjusig animation. */
36
+ floating: boolean;
37
+ /** Vänsterplacerad när floating (default: true). */
38
+ left: boolean;
39
+ /** Högerplacerad när floating (default: false). */
40
+ right: boolean;
41
+ /** Öppen/stängd; kan sättas programmatiskt. */
42
+ open: boolean;
43
+ /** Aktivera global overlay (scrim a.k.a "en tunn gardin"). */
44
+ overlay: boolean;
45
+ /** Lås sidans scroll när overlay och open (default: false). */
46
+ lockScroll: boolean;
47
+ /** Tillåt klick på overlay att stänga (default: true). */
48
+ closeOnOverlay: boolean;
49
+ /** Sätt role="dialog" och aria-modal="true" (kräver overlay och floating som true). */
50
+ modal: boolean;
51
+ /** Senaste trigger-elementet som öppnade drawern (för att kunna återställa fokus vid stängning). */
52
+ private __lastTriggerEl;
53
+ /** Global overlay-instans och relaterad state (delas mellan alla drawers). */
54
+ private static __overlayEl;
55
+ /** Stack för aktiva drawers som använder overlay (överst i stacken får overlay-klick). */
56
+ private static __overlayStack;
57
+ /** Antal aktiva scroll-lås (för att definitivt återställa overflow när sista stängs). */
58
+ private static __lockedCount;
59
+ /** Tidigare overflow-värden som återställs när scroll-lås släpps. */
60
+ private static __prevDocOverflow;
61
+ private static __prevBodyOverflow;
62
+ /** Säkerställ att css för overlay är injicerade en gång per sida. */
63
+ private static __ensureOverlayStyles;
64
+ /** Skapa (vid behov) den globala overlay-noden och koppla stängning på klick. */
65
+ private static __ensureOverlay;
66
+ /** Visa overlay och registrera aktuell drawer som top of the pop i overlay-stacken. */
67
+ private static __showOverlay;
68
+ /** Dölj overlay om det här är sista aktiva drawer; annars ta bort ägaskapr från stacken. */
69
+ private static __hideOverlay;
70
+ /** Aktivera scroll-lås (första gången den aktiveras så sparas tidigare overflow-värden). */
71
+ private static __lockScrollEnable;
72
+ /** Inaktivera scroll-lås och återställ overflow när 0. */
73
+ private static __lockScrollDisable;
74
+ static styles: import('lit').CSSResult;
75
+ render(): TemplateResult;
76
+ connectedCallback(): void;
77
+ disconnectedCallback(): void;
78
+ private _onGlobalSelect;
79
+ private __getActionFromEvent;
80
+ private __onDocumentClick;
81
+ private __onDocumentKeydown;
82
+ /** Hämta tabbale element i den renderade shadow-roten. */
83
+ private __getFocusable;
84
+ /** Sätt endast state; side effects (overlay, fokus, events mm) hanteras i `updated()`. */
85
+ private __setOpen;
86
+ /** Reagera på ändrat `open` oavsett om det kom från triggers eller från kod (drawer.open = …). */
87
+ protected updated(changed: Map<string, unknown>): void;
88
+ /** Overlay-hantering, scroll lock, aria-uppdatering, fokusflytt och öppna/stäng-events. */
89
+ private __applyOpenSideEffects;
90
+ /** Sätt aria-expanded=true/false på alla kontroller som pekar på aktuell drawer via id. */
91
+ private __updateTriggersExpanded;
92
+ }
93
+ declare global {
94
+ interface HTMLElementTagNameMap {
95
+ 'scb-drawer': ScbDrawer;
96
+ }
97
+ }
@@ -0,0 +1,258 @@
1
+ import { css as f, LitElement as u, nothing as d, html as p } from "lit";
2
+ import { property as n, customElement as _ } from "lit/decorators.js";
3
+ import "../scb-divider/scb-divider.js";
4
+ import "./scb-drawer-item.js";
5
+ import "./scb-drawer-section.js";
6
+ import "./scb-sub-drawer.js";
7
+ var h = Object.defineProperty, v = Object.getOwnPropertyDescriptor, a = (t, o, r, s) => {
8
+ for (var l = s > 1 ? void 0 : s ? v(o, r) : o, i = t.length - 1, c; i >= 0; i--)
9
+ (c = t[i]) && (l = (s ? c(o, r, l) : c(l)) || l);
10
+ return s && l && h(o, r, l), l;
11
+ };
12
+ let e = class extends u {
13
+ constructor() {
14
+ super(...arguments), this.label = "", this.subLabel = "", this.floating = !1, this.left = !0, this.right = !1, this.open = !1, this.overlay = !1, this.lockScroll = !1, this.closeOnOverlay = !0, this.modal = !1, this.__lastTriggerEl = null, this._onGlobalSelect = (t) => {
15
+ const o = t;
16
+ this.querySelectorAll("scb-drawer-item").forEach((s) => s.selected = !1), this.contains(o.detail.item) && (o.detail.item.selected = !0);
17
+ }, this.__onDocumentClick = (t) => {
18
+ const o = this.__getActionFromEvent(t);
19
+ if (o) {
20
+ o === "open" && this.__setOpen(!0), o === "close" && this.__setOpen(!1), o === "toggle" && this.__setOpen(!this.open), t.stopPropagation();
21
+ return;
22
+ }
23
+ this.floating && this.open && !this.overlay && (t.composedPath().includes(this) || this.__setOpen(!1));
24
+ }, this.__onDocumentKeydown = (t) => {
25
+ if (this.open) {
26
+ if (t.key === "Escape") {
27
+ this.__setOpen(!1);
28
+ return;
29
+ }
30
+ if (this.overlay && t.key === "Tab") {
31
+ const o = this.__getFocusable();
32
+ if (o.length === 0) return;
33
+ const r = o[0], s = o[o.length - 1], l = this.renderRoot, i = l.activeElement || document.activeElement;
34
+ t.shiftKey ? (i === r || !l.contains(i)) && (t.preventDefault(), s.focus()) : (i === s || !l.contains(i)) && (t.preventDefault(), r.focus());
35
+ }
36
+ }
37
+ };
38
+ }
39
+ /** Säkerställ att css för overlay är injicerade en gång per sida. */
40
+ static __ensureOverlayStyles() {
41
+ if (typeof document > "u" || document.getElementById("scb-drawer-overlay-styles")) return;
42
+ const t = document.createElement("style");
43
+ t.id = "scb-drawer-overlay-styles", t.textContent = `
44
+ .scb-drawer-global-overlay {
45
+ position: fixed;
46
+ inset: 0;
47
+ background: var(--scb-drawer-overlay-color, rgba(0,0,0,0.32));
48
+ opacity: 0;
49
+ pointer-events: none;
50
+ transition: opacity 200ms ease;
51
+ z-index: var(--scb-drawer-overlay-z, 999);
52
+ }
53
+ .scb-drawer-global-overlay.is-visible {
54
+ opacity: 1;
55
+ pointer-events: auto;
56
+ }
57
+ `, document.head.appendChild(t);
58
+ }
59
+ /** Skapa (vid behov) den globala overlay-noden och koppla stängning på klick. */
60
+ static __ensureOverlay() {
61
+ if (typeof document > "u" || e.__overlayEl) return;
62
+ e.__ensureOverlayStyles();
63
+ const t = document.createElement("div");
64
+ t.className = "scb-drawer-global-overlay", t.addEventListener("mousedown", () => {
65
+ const o = e.__overlayStack[e.__overlayStack.length - 1];
66
+ o && o.closeOnOverlay && o.__setOpen(!1);
67
+ }), document.body.appendChild(t), e.__overlayEl = t;
68
+ }
69
+ /** Visa overlay och registrera aktuell drawer som top of the pop i overlay-stacken. */
70
+ static __showOverlay(t) {
71
+ e.__ensureOverlay(), e.__overlayEl && (e.__overlayStack.includes(t) || e.__overlayStack.push(t), e.__overlayEl.classList.add("is-visible"));
72
+ }
73
+ /** Dölj overlay om det här är sista aktiva drawer; annars ta bort ägaskapr från stacken. */
74
+ static __hideOverlay(t) {
75
+ const o = e.__overlayStack.indexOf(t);
76
+ o >= 0 && e.__overlayStack.splice(o, 1), e.__overlayStack.length === 0 && e.__overlayEl && e.__overlayEl.classList.remove("is-visible");
77
+ }
78
+ /** Aktivera scroll-lås (första gången den aktiveras så sparas tidigare overflow-värden). */
79
+ static __lockScrollEnable() {
80
+ typeof document > "u" || (e.__lockedCount === 0 && (e.__prevDocOverflow = document.documentElement.style.overflow || "", e.__prevBodyOverflow = document.body.style.overflow || "", document.documentElement.style.overflow = "hidden", document.body.style.overflow = "hidden"), e.__lockedCount++);
81
+ }
82
+ /** Inaktivera scroll-lås och återställ overflow när 0. */
83
+ static __lockScrollDisable() {
84
+ typeof document > "u" || (e.__lockedCount = Math.max(0, e.__lockedCount - 1), e.__lockedCount === 0 && (document.documentElement.style.overflow = e.__prevDocOverflow ?? "", document.body.style.overflow = e.__prevBodyOverflow ?? ""));
85
+ }
86
+ render() {
87
+ const t = this.modal && this.overlay && this.floating;
88
+ return p`
89
+ <nav
90
+ aria-label="${this.label}"
91
+ role=${t ? "dialog" : d}
92
+ aria-modal=${t ? "true" : d}
93
+ >
94
+ ${this.label ? p`
95
+ <div class="scb-drawer-label-wrapper">
96
+ <div class="scb-drawer-label">${this.label}</div>
97
+ <div class="scb-drawer-sublabel">${this.subLabel}</div>
98
+ </div>
99
+ <scb-divider></scb-divider>
100
+ ` : d}
101
+ <slot></slot>
102
+ </nav>
103
+ `;
104
+ }
105
+ connectedCallback() {
106
+ super.connectedCallback(), window.addEventListener("scb-drawer-select", this._onGlobalSelect), document.addEventListener("click", this.__onDocumentClick, !1), document.addEventListener("keydown", this.__onDocumentKeydown, !0);
107
+ }
108
+ disconnectedCallback() {
109
+ window.removeEventListener("scb-drawer-select", this._onGlobalSelect), document.removeEventListener("click", this.__onDocumentClick, !1), document.removeEventListener("keydown", this.__onDocumentKeydown, !0), this.overlay && (e.__hideOverlay(this), this.lockScroll && e.__lockScrollDisable()), super.disconnectedCallback();
110
+ }
111
+ // Kolla trigger via composedPath() (fungerar i shadow DOM)
112
+ __getActionFromEvent(t) {
113
+ if (!this.id) return null;
114
+ const o = t.composedPath();
115
+ for (const r of o)
116
+ if (r instanceof Element) {
117
+ if (r.getAttribute("data-drawer-open") === this.id)
118
+ return this.__lastTriggerEl = r, "open";
119
+ if (r.getAttribute("data-drawer-close") === this.id)
120
+ return this.__lastTriggerEl = r, "close";
121
+ if (r.getAttribute("data-drawer-toggle") === this.id)
122
+ return this.__lastTriggerEl = r, "toggle";
123
+ if (r.getAttribute("aria-controls") === this.id)
124
+ return this.__lastTriggerEl = r, "toggle";
125
+ }
126
+ return null;
127
+ }
128
+ /** Hämta tabbale element i den renderade shadow-roten. */
129
+ __getFocusable() {
130
+ const t = this.renderRoot;
131
+ return Array.from(
132
+ t.querySelectorAll(
133
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
134
+ )
135
+ ).filter((o) => !o.hasAttribute("disabled") && o.tabIndex >= 0);
136
+ }
137
+ /** Sätt endast state; side effects (overlay, fokus, events mm) hanteras i `updated()`. */
138
+ __setOpen(t) {
139
+ this.open = t;
140
+ }
141
+ /** Reagera på ändrat `open` oavsett om det kom från triggers eller från kod (drawer.open = …). */
142
+ updated(t) {
143
+ if (t.has("open")) {
144
+ const o = t.get("open");
145
+ this.__applyOpenSideEffects(o, this.open);
146
+ }
147
+ t.has("right") && this.right && this.left && (this.left = !1), t.has("left") && this.left && this.right && (this.right = !1);
148
+ }
149
+ /** Overlay-hantering, scroll lock, aria-uppdatering, fokusflytt och öppna/stäng-events. */
150
+ __applyOpenSideEffects(t, o) {
151
+ var r, s;
152
+ this.floating && this.overlay && (o ? (e.__showOverlay(this), this.lockScroll && e.__lockScrollEnable()) : (e.__hideOverlay(this), this.lockScroll && e.__lockScrollDisable())), this.__updateTriggersExpanded(), o && !t ? (this.updateComplete.then(() => {
153
+ var i;
154
+ const l = this.__getFocusable()[0];
155
+ (i = l == null ? void 0 : l.focus) == null || i.call(l);
156
+ }), this.dispatchEvent(new CustomEvent("scb-drawer-opened", { bubbles: !0, composed: !0 }))) : !o && t && ((s = (r = this.__lastTriggerEl) == null ? void 0 : r.focus) == null || s.call(r), this.dispatchEvent(new CustomEvent("scb-drawer-closed", { bubbles: !0, composed: !0 })));
157
+ }
158
+ /** Sätt aria-expanded=true/false på alla kontroller som pekar på aktuell drawer via id. */
159
+ __updateTriggersExpanded() {
160
+ if (!this.id) return;
161
+ document.querySelectorAll(
162
+ `[aria-controls="${this.id}"], [data-drawer-open="${this.id}"], [data-drawer-close="${this.id}"], [data-drawer-toggle="${this.id}"]`
163
+ ).forEach((o) => {
164
+ o.hasAttribute("aria-controls") && o.setAttribute("aria-expanded", String(this.open));
165
+ });
166
+ }
167
+ };
168
+ e.__overlayEl = null;
169
+ e.__overlayStack = [];
170
+ e.__lockedCount = 0;
171
+ e.__prevDocOverflow = null;
172
+ e.__prevBodyOverflow = null;
173
+ e.styles = f`
174
+ :host {
175
+ display: block;
176
+ color: var(--md-sys-color-on-surface);
177
+ padding: 12px;
178
+ background: var(--md-sys-color-surface-container-low);
179
+ }
180
+
181
+ /* Floating drawer */
182
+ :host([floating]) {
183
+ position: fixed;
184
+ top: 0;
185
+ height: 100vh;
186
+ width: clamp(280px, 70vw, 360px);
187
+ background: var(--md-sys-color-surface-container-low);
188
+ box-shadow: 2px 0 12px rgba(0,0,0,0.15);
189
+ z-index: var(--scb-drawer-z, 1000);
190
+ transition: transform 0.3s ease, opacity 0.3s ease, visibility 0.3s;
191
+ opacity: 0;
192
+ visibility: hidden;
193
+ pointer-events: none;
194
+ }
195
+
196
+ /* Vänsterläge (default) */
197
+ :host([floating][left]) { left: 0; transform: translateX(-100%); }
198
+ :host([floating][left][open]) {
199
+ transform: translateX(0);
200
+ opacity: 1;
201
+ visibility: visible;
202
+ pointer-events: auto;
203
+ }
204
+
205
+ /* Högerläge */
206
+ :host([floating][right]) {
207
+ right: 0;
208
+ transform: translateX(100%);
209
+ box-shadow: -2px 0 12px rgba(0,0,0,0.15);
210
+ }
211
+ :host([floating][right][open]) {
212
+ transform: translateX(0);
213
+ opacity: 1;
214
+ visibility: visible;
215
+ pointer-events: auto;
216
+ }
217
+
218
+ .scb-drawer-label { font-size: 16px; font-weight: 600; line-height: 24px; }
219
+ .scb-drawer-sublabel { font-size: 14px; line-height: 20px; }
220
+ .scb-drawer-label-wrapper { padding: 12px; color: inherit; }
221
+ scb-divider { margin: 4px 12px; }
222
+ `;
223
+ a([
224
+ n({ type: String })
225
+ ], e.prototype, "label", 2);
226
+ a([
227
+ n({ type: String, attribute: "sub-label" })
228
+ ], e.prototype, "subLabel", 2);
229
+ a([
230
+ n({ type: Boolean, reflect: !0 })
231
+ ], e.prototype, "floating", 2);
232
+ a([
233
+ n({ type: Boolean, reflect: !0 })
234
+ ], e.prototype, "left", 2);
235
+ a([
236
+ n({ type: Boolean, reflect: !0 })
237
+ ], e.prototype, "right", 2);
238
+ a([
239
+ n({ type: Boolean, reflect: !0 })
240
+ ], e.prototype, "open", 2);
241
+ a([
242
+ n({ type: Boolean, reflect: !0 })
243
+ ], e.prototype, "overlay", 2);
244
+ a([
245
+ n({ type: Boolean, reflect: !0, attribute: "lock-scroll" })
246
+ ], e.prototype, "lockScroll", 2);
247
+ a([
248
+ n({ type: Boolean, reflect: !0, attribute: "close-on-overlay" })
249
+ ], e.prototype, "closeOnOverlay", 2);
250
+ a([
251
+ n({ type: Boolean, reflect: !0 })
252
+ ], e.prototype, "modal", 2);
253
+ e = a([
254
+ _("scb-drawer")
255
+ ], e);
256
+ export {
257
+ e as ScbDrawer
258
+ };
@@ -0,0 +1,10 @@
1
+ import { LitElement, TemplateResult } from 'lit';
2
+
3
+ export declare class ScbSubDrawer extends LitElement {
4
+ label: string;
5
+ static styles: import('lit').CSSResult;
6
+ connectedCallback(): void;
7
+ disconnectedCallback(): void;
8
+ private _onGlobalSelect;
9
+ render(): TemplateResult;
10
+ }
@@ -0,0 +1,43 @@
1
+ import { css as i, LitElement as b, html as d } from "lit";
2
+ import { property as p, customElement as m } from "lit/decorators.js";
3
+ var u = Object.defineProperty, h = Object.getOwnPropertyDescriptor, n = (s, e, r, l) => {
4
+ for (var t = l > 1 ? void 0 : l ? h(e, r) : e, o = s.length - 1, a; o >= 0; o--)
5
+ (a = s[o]) && (t = (l ? a(e, r, t) : a(t)) || t);
6
+ return l && t && u(e, r, t), t;
7
+ };
8
+ let c = class extends b {
9
+ constructor() {
10
+ super(...arguments), this.label = "", this._onGlobalSelect = (s) => {
11
+ const e = s;
12
+ this.querySelectorAll("scb-drawer-item").forEach((l) => l.selected = !1), this.contains(e.detail.item) && (e.detail.item.selected = !0);
13
+ };
14
+ }
15
+ connectedCallback() {
16
+ super.connectedCallback(), window.addEventListener("scb-drawer-select", this._onGlobalSelect);
17
+ }
18
+ disconnectedCallback() {
19
+ window.removeEventListener("scb-drawer-select", this._onGlobalSelect), super.disconnectedCallback();
20
+ }
21
+ render() {
22
+ return d`
23
+ <nav aria-label="${this.label}">
24
+ <slot></slot>
25
+ </nav>
26
+ `;
27
+ }
28
+ };
29
+ c.styles = i`
30
+ :host {
31
+ display: block;
32
+ width: 100%;
33
+ }
34
+ `;
35
+ n([
36
+ p({ type: String })
37
+ ], c.prototype, "label", 2);
38
+ c = n([
39
+ m("scb-sub-drawer")
40
+ ], c);
41
+ export {
42
+ c as ScbSubDrawer
43
+ };