scb-wc-test 0.1.110 → 0.1.112

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.
@@ -58,6 +58,18 @@
58
58
  function mirrorHeaderDrawer(el, isOpen) {
59
59
  if (isOpen) el.setAttribute('drawer-open', '');
60
60
  else el.removeAttribute('drawer-open');
61
+
62
+ // Spegla aria-expanded på menyknappen i headerns shadow DOM så att läget blir rätt även vid overlay-stängning
63
+ try {
64
+ const sr = el.shadowRoot;
65
+ if (sr) {
66
+ const btn =
67
+ sr.querySelector('.menu-trigger') ||
68
+ sr.querySelector('[data-drawer-toggle]') ||
69
+ sr.querySelector('[aria-controls]');
70
+ if (btn) btn.setAttribute('aria-expanded', String(!!isOpen));
71
+ }
72
+ } catch (_) {}
61
73
  }
62
74
 
63
75
  function mirrorHeaderSearch(el, ev) {
@@ -91,6 +103,19 @@
91
103
  to: 'draweropen',
92
104
  mirror: (el) => mirrorHeaderDrawer(el, false),
93
105
  },
106
+ // Speglar headerns drawer-state även när drawern stängs/öppnas via overlay eller ESC
107
+ {
108
+ sel: 'scb-header',
109
+ from: 'scb-drawer-opened',
110
+ to: 'scb-drawer-opened',
111
+ mirror: (el) => mirrorHeaderDrawer(el, true),
112
+ },
113
+ {
114
+ sel: 'scb-header',
115
+ from: 'scb-drawer-closed',
116
+ to: 'scb-drawer-closed',
117
+ mirror: (el) => mirrorHeaderDrawer(el, false),
118
+ },
94
119
  { sel: 'scb-header', from: 'drawer-select', to: 'select' },
95
120
  { sel: 'scb-header', from: 'menu-click', to: 'menuclick' },
96
121
  {
@@ -1968,6 +1993,46 @@ window.SCBBlazor.registerScbEventHandlers = function (dotNetRef) {
1968
1993
  (function () {
1969
1994
  'use strict';
1970
1995
 
1996
+ function buildAttrSelector(attr, value) {
1997
+ const v = String(value ?? '')
1998
+ .replace(/\\/g, '\\\\')
1999
+ .replace(/"/g, '\\"');
2000
+ return `[${attr}="${v}"]`;
2001
+ }
2002
+
2003
+ function getOpenState(el) {
2004
+ if (!el) return false;
2005
+ try {
2006
+ if (typeof el.open === 'boolean') return el.open;
2007
+ } catch (_) {}
2008
+ return el.hasAttribute && el.hasAttribute('open');
2009
+ }
2010
+
2011
+ function safeClick(el) {
2012
+ if (!el) return false;
2013
+ try {
2014
+ el.dispatchEvent(
2015
+ new MouseEvent('click', { bubbles: true, composed: true }),
2016
+ );
2017
+ return true;
2018
+ } catch (_) {}
2019
+ try {
2020
+ el.click();
2021
+ return true;
2022
+ } catch (_) {}
2023
+ return false;
2024
+ }
2025
+
2026
+ function findTrigger(kind, id, wantOpen) {
2027
+ if (!id) return null;
2028
+ const selectors = [];
2029
+ if (wantOpen) selectors.push(buildAttrSelector(`data-${kind}-open`, id));
2030
+ else selectors.push(buildAttrSelector(`data-${kind}-close`, id));
2031
+ selectors.push(buildAttrSelector(`data-${kind}-toggle`, id));
2032
+ selectors.push(buildAttrSelector('aria-controls', id));
2033
+ return document.querySelector(selectors.join(','));
2034
+ }
2035
+
1971
2036
  function getByIndex(selector, index) {
1972
2037
  const list = document.querySelectorAll(selector);
1973
2038
  if (!list || list.length === 0) return null;
@@ -2018,8 +2083,50 @@ window.SCBBlazor.registerScbEventHandlers = function (dotNetRef) {
2018
2083
  const header = document.querySelector('scb-header');
2019
2084
  if (!header) return;
2020
2085
  const isOpen = toBool(open);
2021
- if (isOpen) header.setAttribute('drawer-open', '');
2022
- else header.removeAttribute('drawer-open');
2086
+
2087
+ // Markör på hosten används av getState för Header.DrawerOpen
2088
+ try {
2089
+ mirrorHeaderDrawer(header, isOpen);
2090
+ } catch (_) {
2091
+ if (isOpen) header.setAttribute('drawer-open', '');
2092
+ else header.removeAttribute('drawer-open');
2093
+ }
2094
+
2095
+ // Styr drawern som ligger inuti headerns shadow DOM (standard id: main-drawer)
2096
+ try {
2097
+ const sr = header.shadowRoot;
2098
+ if (sr) {
2099
+ const btn =
2100
+ sr.querySelector('.menu-trigger') ||
2101
+ sr.querySelector('[data-drawer-toggle]') ||
2102
+ sr.querySelector('[aria-controls]');
2103
+
2104
+ const drawerId =
2105
+ (btn &&
2106
+ (btn.getAttribute('aria-controls') ||
2107
+ btn.getAttribute('data-drawer-toggle'))) ||
2108
+ 'main-drawer';
2109
+
2110
+ const safeId =
2111
+ window.CSS && typeof window.CSS.escape === 'function'
2112
+ ? window.CSS.escape(String(drawerId))
2113
+ : String(drawerId);
2114
+
2115
+ const drawer =
2116
+ sr.querySelector(`#${safeId}`) ||
2117
+ sr.querySelector('scb-drawer');
2118
+
2119
+ if (drawer) {
2120
+ try {
2121
+ drawer.open = isOpen;
2122
+ } catch (_) {}
2123
+ if (isOpen) drawer.setAttribute('open', '');
2124
+ else drawer.removeAttribute('open');
2125
+ }
2126
+ }
2127
+ } catch (_) {}
2128
+
2129
+ // Trigga state-refresh i Blazor
2023
2130
  dispatchChange(header, 'draweropen', { open: isOpen });
2024
2131
  };
2025
2132
 
@@ -2037,16 +2144,28 @@ window.SCBBlazor.registerScbEventHandlers = function (dotNetRef) {
2037
2144
 
2038
2145
  // Drawer och menu
2039
2146
 
2040
- api.setDrawerOpen = function (open) {
2147
+ api.setDrawerOpen = function (open) {
2041
2148
  const drawer = document.querySelector('scb-drawer');
2042
2149
  if (!drawer) return;
2150
+
2043
2151
  const isOpen = toBool(open);
2152
+ const prev = getOpenState(drawer);
2153
+ if (prev === isOpen) return;
2154
+
2155
+ // Primärt: använd samma trigger-logik som i UI:t (aria-controls / data-drawer-*)
2156
+ const id = drawer.id;
2157
+ const trigger = findTrigger('drawer', id, isOpen);
2158
+ if (trigger) {
2159
+ safeClick(trigger);
2160
+ if (getOpenState(drawer) === isOpen) return;
2161
+ }
2162
+
2163
+ // Fallback: sätt open direkt
2044
2164
  try {
2045
2165
  drawer.open = isOpen;
2046
2166
  } catch (_) {}
2047
2167
  if (isOpen) drawer.setAttribute('open', '');
2048
2168
  else drawer.removeAttribute('open');
2049
- dispatchChange(drawer, 'openchange', { open: isOpen });
2050
2169
  };
2051
2170
 
2052
2171
  api.setDrawerText = function (label, subLabel) {
@@ -2273,15 +2392,40 @@ window.SCBBlazor.registerScbEventHandlers = function (dotNetRef) {
2273
2392
 
2274
2393
  // Dialog, notification och snackbar
2275
2394
 
2276
- api.setDialogOpen = function (open) {
2395
+ api.setDialogOpen = function (open) {
2277
2396
  const dialog = document.querySelector('scb-dialog');
2278
2397
  if (!dialog) return;
2398
+
2279
2399
  const isOpen = toBool(open);
2400
+ const prev = getOpenState(dialog);
2401
+ if (prev === isOpen) return;
2402
+
2403
+ // Primärt: använd samma trigger-logik som i UI:t (aria-controls / data-dialog-*)
2404
+ const id = dialog.id;
2405
+ const trigger = findTrigger('dialog', id, isOpen);
2406
+ if (trigger) {
2407
+ safeClick(trigger);
2408
+ if (getOpenState(dialog) === isOpen) {
2409
+ // Dialogen behöver en normaliserad event-signal för att Blazor ska uppdatera state
2410
+ dispatchChange(dialog, 'openchange', { open: isOpen });
2411
+ return;
2412
+ }
2413
+ }
2414
+
2415
+ // Fallback: försök komponentens API om det finns
2416
+ try {
2417
+ if (isOpen && typeof dialog.showModal === 'function') dialog.showModal();
2418
+ else if (isOpen && typeof dialog.show === 'function') dialog.show();
2419
+ else if (!isOpen && typeof dialog.close === 'function') dialog.close();
2420
+ } catch (_) {}
2421
+
2422
+ // Sista fallback: sätt open direkt
2280
2423
  try {
2281
2424
  dialog.open = isOpen;
2282
2425
  } catch (_) {}
2283
2426
  if (isOpen) dialog.setAttribute('open', '');
2284
2427
  else dialog.removeAttribute('open');
2428
+
2285
2429
  dispatchChange(dialog, 'openchange', { open: isOpen });
2286
2430
  };
2287
2431
 
@@ -2514,4 +2658,148 @@ window.SCBBlazor.registerScbEventHandlers = function (dotNetRef) {
2514
2658
  } catch (_) {}
2515
2659
  dispatchChange(viz, 'valuechange', { value });
2516
2660
  };
2661
+
2662
+ api.setVizView = function (index, view) {
2663
+ const viz = getByIndex('scb-viz', index);
2664
+ if (!viz) return;
2665
+ setVizViewOnElement(viz, view);
2666
+ };
2667
+
2668
+ api.setVizViewById = function (id, view) {
2669
+ const viz = getById(id, 'scb-viz');
2670
+ if (!viz) return;
2671
+ setVizViewOnElement(viz, view);
2672
+ };
2673
+
2674
+ function setVizViewOnElement(viz, view) {
2675
+ const raw = view == null ? '' : String(view);
2676
+ const v = raw.trim().toLowerCase();
2677
+ const showTable = v === 'table' || v === 'tabell';
2678
+
2679
+ // Försöker först styra via viz egna UI (segmented) så att både vy och vald knapp hamnar i synk.
2680
+ try {
2681
+ const sr = viz.shadowRoot;
2682
+ if (sr) {
2683
+ const scbSegmented = sr.querySelector('scb-segmented-button');
2684
+ if (scbSegmented) {
2685
+ const targetLabel = showTable ? 'tabell' : 'diagram';
2686
+ const targetLabelAlt = showTable ? 'table' : 'chart';
2687
+
2688
+ const items = Array.from(
2689
+ scbSegmented.querySelectorAll('scb-segmented-item, button, [role="button"]'),
2690
+ );
2691
+
2692
+ const pickByLabel = (el) => {
2693
+ const label = (
2694
+ el.getAttribute('label') ||
2695
+ el.getAttribute('aria-label') ||
2696
+ (el.label ?? '')
2697
+ )
2698
+ .toString()
2699
+ .trim()
2700
+ .toLowerCase();
2701
+ const text = (el.textContent ?? '').toString().trim().toLowerCase();
2702
+ const s = `${label} ${text}`.trim();
2703
+ return s.includes(targetLabel) || s.includes(targetLabelAlt);
2704
+ };
2705
+
2706
+ let targetEl = items.find(pickByLabel);
2707
+ if (!targetEl && items.length >= 2) {
2708
+ targetEl = items[showTable ? 1 : 0];
2709
+ }
2710
+
2711
+ if (targetEl) {
2712
+ const itemValue = (
2713
+ targetEl.getAttribute('value') ||
2714
+ targetEl.getAttribute('data-value') ||
2715
+ (targetEl.value ?? '')
2716
+ )
2717
+ .toString()
2718
+ .trim();
2719
+
2720
+ if (itemValue) {
2721
+ try {
2722
+ scbSegmented.value = itemValue;
2723
+ } catch (_) {}
2724
+ }
2725
+
2726
+ if (typeof targetEl.click === 'function') {
2727
+ targetEl.click();
2728
+ }
2729
+
2730
+ return;
2731
+ }
2732
+ }
2733
+
2734
+ // Fallback för Material/Web eller annan intern implementation där knapparna ligger direkt i shadowRoot.
2735
+ const mdButtons = Array.from(sr.querySelectorAll('md-segmented-button'));
2736
+ const buttons = mdButtons.length
2737
+ ? mdButtons
2738
+ : Array.from(sr.querySelectorAll('button, [role="button"]'));
2739
+
2740
+ if (buttons.length) {
2741
+ const targetLabel = showTable ? 'tabell' : 'diagram';
2742
+ const targetLabelAlt = showTable ? 'table' : 'chart';
2743
+
2744
+ const pickByLabel = (el) => {
2745
+ const label = (
2746
+ el.getAttribute('label') ||
2747
+ el.getAttribute('aria-label') ||
2748
+ (el.label ?? '')
2749
+ )
2750
+ .toString()
2751
+ .trim()
2752
+ .toLowerCase();
2753
+ const text = (el.textContent ?? '').toString().trim().toLowerCase();
2754
+ const s = `${label} ${text}`.trim();
2755
+ return s.includes(targetLabel) || s.includes(targetLabelAlt);
2756
+ };
2757
+
2758
+ let targetEl = buttons.find(pickByLabel);
2759
+ if (!targetEl && buttons.length >= 2) {
2760
+ targetEl = buttons[showTable ? 1 : 0];
2761
+ }
2762
+
2763
+ if (targetEl) {
2764
+ if (typeof targetEl.click === 'function') {
2765
+ targetEl.click();
2766
+ return;
2767
+ }
2768
+
2769
+ try {
2770
+ targetEl.dispatchEvent(
2771
+ new MouseEvent('click', { bubbles: true, composed: true }),
2772
+ );
2773
+ return;
2774
+ } catch (_) {}
2775
+ }
2776
+ }
2777
+ }
2778
+ } catch (_) {}
2779
+
2780
+ // Sista fallback: växlar synlighet på slottat innehåll.
2781
+ const diagramSlot = viz.querySelector('[slot="diagram"]');
2782
+ const tableSlot = viz.querySelector('[slot="table"]');
2783
+
2784
+ if (diagramSlot) {
2785
+ if (showTable) {
2786
+ diagramSlot.setAttribute('hidden', '');
2787
+ diagramSlot.style.setProperty('display', 'none', 'important');
2788
+ } else {
2789
+ diagramSlot.removeAttribute('hidden');
2790
+ diagramSlot.style.removeProperty('display');
2791
+ }
2792
+ }
2793
+
2794
+ if (tableSlot) {
2795
+ if (showTable) {
2796
+ tableSlot.removeAttribute('hidden');
2797
+ tableSlot.style.removeProperty('display');
2798
+ } else {
2799
+ tableSlot.setAttribute('hidden', '');
2800
+ tableSlot.style.setProperty('display', 'none', 'important');
2801
+ }
2802
+ }
2803
+ };
2804
+
2517
2805
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scb-wc-test",
3
- "version": "0.1.110",
3
+ "version": "0.1.112",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -341,5 +341,5 @@
341
341
  },
342
342
  "./mvc/*": "./mvc/*"
343
343
  },
344
- "buildHash": "F142DFDCE174D0D5DCDD14FD8B10957969B9FD7FAB93E461E9DBCBE6E86A3E73"
344
+ "buildHash": "B10F313B2C3B27480883227E72110DB0EB6C38251188E14A847823D36B266345"
345
345
  }
@@ -1,26 +1,35 @@
1
1
  import { css as v, LitElement as x, html as c } from "lit";
2
- import { property as a, customElement as y } from "lit/decorators.js";
2
+ import { property as a, state as g, customElement as y } from "lit/decorators.js";
3
3
  import "@material/web/icon/icon.js";
4
- import "../scb-datepicker/scb-datepicker.js";
5
4
  import "@material/web/ripple/ripple.js";
6
5
  import "@material/web/focus/md-focus-ring.js";
7
- var g = Object.defineProperty, w = Object.getOwnPropertyDescriptor, m = (t) => {
6
+ import "../scb-datepicker/scb-datepicker.js";
7
+ import "../scb-icon-button/scb-icon-button.js";
8
+ var w = Object.defineProperty, _ = Object.getOwnPropertyDescriptor, m = (t) => {
8
9
  throw TypeError(t);
9
- }, r = (t, e, i, o) => {
10
- for (var l = o > 1 ? void 0 : o ? w(e, i) : e, u = t.length - 1, b; u >= 0; u--)
11
- (b = t[u]) && (l = (o ? b(e, i, l) : b(l)) || l);
12
- return o && l && g(e, i, l), l;
13
- }, _ = (t, e, i) => e.has(t) || m("Cannot " + i), k = (t, e, i) => e.has(t) ? m("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, i), d = (t, e, i) => (_(t, e, "access private method"), i), n, f, h, p;
10
+ }, r = (t, e, i, l) => {
11
+ for (var n = l > 1 ? void 0 : l ? _(e, i) : e, u = t.length - 1, b; u >= 0; u--)
12
+ (b = t[u]) && (n = (l ? b(e, i, n) : b(n)) || n);
13
+ return l && n && w(e, i, n), n;
14
+ }, k = (t, e, i) => e.has(t) || m("Cannot " + i), $ = (t, e, i) => e.has(t) ? m("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(t) : e.set(t, i), d = (t, e, i) => (k(t, e, "access private method"), i), o, f, h, p;
14
15
  let s = class extends x {
15
16
  constructor() {
16
- super(), k(this, n), this._internals = null, this._inputFocused = !1, this._kbShouldShowRing = !1, this._onGlobalKeydown = (t) => {
17
- t.key === "Tab" && (this._kbShouldShowRing = !0, this._inputFocused && d(this, n, p).call(this));
17
+ super(), $(this, o), this._internals = null, this._inputFocused = !1, this._kbShouldShowRing = !1, this._onGlobalKeydown = (t) => {
18
+ t.key === "Tab" && (this._kbShouldShowRing = !0, this._inputFocused && d(this, o, p).call(this));
18
19
  }, this._onGlobalPointerDown = () => {
19
- this._kbShouldShowRing = !1, this._inputFocused && d(this, n, p).call(this);
20
+ this._kbShouldShowRing = !1, this._inputFocused && d(this, o, p).call(this);
20
21
  }, this.type = "text", this.label = "", this.supportingText = "", this.errorText = "", this.leadingIcon = "", this.name = "", this.pattern = "", this.value = "", this.underLabel = "", this.error = !1, this.disabled = !1, this.required = !1, this.spacing = "", this.spacingTop = "", this.spacingBottom = "", this._form = null, this._formSubmitHandler = null, this._formResetHandler = null, this._initialValue = "", this._inputId = "", this._showDatepicker = !1, this._toggleDatepicker = () => {
21
22
  this._showDatepicker = !this._showDatepicker;
22
23
  }, this._onDateSelected = (t) => {
23
- this.value = t.detail.value, this._showDatepicker = !1, this.dispatchEvent(new Event("input", { bubbles: !0, composed: !0 })), this.dispatchEvent(
24
+ if (this.value = t.detail.value, this._showDatepicker = !1, this._internals) {
25
+ const e = this.disabled ? null : this.value;
26
+ this._internals.setFormValue(e);
27
+ }
28
+ if (this.pattern) {
29
+ const e = new RegExp(this.pattern);
30
+ this.error = !e.test(this.value);
31
+ }
32
+ this.dispatchEvent(new Event("input", { bubbles: !0, composed: !0 })), this.dispatchEvent(
24
33
  new CustomEvent("onValueChanged", {
25
34
  detail: { value: this.value },
26
35
  bubbles: !0,
@@ -32,7 +41,7 @@ let s = class extends x {
32
41
  render() {
33
42
  const t = this.leadingIcon ? c`<md-icon class="scb-textfield-icon">${this.leadingIcon}</md-icon>` : null, e = this.error ? c`<md-icon class="scb-textfield-error-icon" aria-hidden="true">error</md-icon>` : null;
34
43
  this.underLabel = this.error ? this.errorText || "Ogiltig inmatning." : this.supportingText, this.value = this.value || "";
35
- const i = this.underLabel ? `${this._inputId}-supporting-text` : void 0, o = this.type === "search" && this.value ? c`
44
+ const i = this.underLabel ? `${this._inputId}-supporting-text` : void 0, l = this.type === "search" && this.value ? c`
36
45
  <button
37
46
  type="button"
38
47
  class="scb-textfield-clear"
@@ -74,20 +83,22 @@ let s = class extends x {
74
83
  id="${this.underLabel ? `${this._inputId}-supporting-text` : ""}"
75
84
  >${this.underLabel}</span
76
85
  >
77
- <div class="scb-textfield-wrapper ripple-wrapper">
78
- <textarea
79
- class="scb-textfield"
80
- ?disabled=${this.disabled}
81
- name="${this.name}"
82
- id="${this._inputId}"
83
- ?required=${this.required}
84
- aria-invalid=${this.error ? "true" : "false"}
85
- aria-describedby=${i}
86
- >
86
+ <div class="scb-textfield-wrapper">
87
+ <div class="ripple-wrapper">
88
+ <textarea
89
+ class="scb-textfield"
90
+ ?disabled=${this.disabled}
91
+ name="${this.name}"
92
+ id="${this._inputId}"
93
+ ?required=${this.required}
94
+ aria-invalid=${this.error ? "true" : "false"}
95
+ aria-describedby=${i}
96
+ >
87
97
  ${this.value}</textarea
88
- >
89
- <md-ripple></md-ripple>
90
- <md-focus-ring class="input-ring"></md-focus-ring>
98
+ >
99
+ <md-ripple></md-ripple>
100
+ <md-focus-ring class="input-ring"></md-focus-ring>
101
+ </div>
91
102
  </div>
92
103
  ` : this.type === "date" ? c`
93
104
  <label class="scb-textfield-label" for="${this._inputId}">${this.label}</label>
@@ -96,28 +107,37 @@ ${this.value}</textarea
96
107
  id="${this.underLabel ? `${this._inputId}-supporting-text` : ""}"
97
108
  >${this.underLabel}</span
98
109
  >
99
- <div class="scb-textfield-wrapper" style="position:relative;">
110
+ <div class="scb-textfield-wrapper">
100
111
  ${t}
101
- <input
102
- class="scb-textfield${this.error ? " has-error-icon" : ""}"
103
- .value=${this.value}
104
- type="text"
105
- name="${this.name}"
106
- id="${this._inputId}"
107
- ?disabled=${this.disabled}
108
- ?required=${this.required}
109
- aria-invalid=${this.error ? "true" : "false"}
110
- aria-describedby=${i}
111
- readonly
112
- />
113
- <scb-icon-button icon="calendar_today" @click=${this._toggleDatepicker} aria-label="Välj datum" style="position:absolute;right:8px;top:50%;transform:translateY(-50%);"></scb-icon-button>
112
+ <div class="ripple-wrapper">
113
+ <input
114
+ class="scb-textfield${this.error ? " has-error-icon" : ""}"
115
+ .value=${this.value}
116
+ type="text"
117
+ name="${this.name}"
118
+ id="${this._inputId}"
119
+ ?disabled=${this.disabled}
120
+ ?required=${this.required}
121
+ aria-invalid=${this.error ? "true" : "false"}
122
+ aria-describedby=${i}
123
+ readonly
124
+ />
125
+ ${e}
126
+ <md-ripple></md-ripple>
127
+ <md-focus-ring class="input-ring"></md-focus-ring>
128
+ </div>
129
+ <scb-icon-button
130
+ class="scb-textfield-datepicker-button"
131
+ icon="calendar_today"
132
+ @click=${this._toggleDatepicker}
133
+ aria-label="Välj datum"
134
+ ></scb-icon-button>
114
135
  <scb-datepicker
115
136
  variant="popup"
116
137
  .selectedValue=${this.value}
117
138
  .open=${this._showDatepicker}
118
139
  @date-selected=${this._onDateSelected}
119
140
  ></scb-datepicker>
120
- ${e}
121
141
  </div>
122
142
  ` : c`
123
143
  <label class="scb-textfield-label" for="${this._inputId}">${this.label}</label>
@@ -126,23 +146,25 @@ ${this.value}</textarea
126
146
  id="${this.underLabel ? `${this._inputId}-supporting-text` : ""}"
127
147
  >${this.underLabel}</span
128
148
  >
129
- <div class="scb-textfield-wrapper ripple-wrapper">
149
+ <div class="scb-textfield-wrapper">
130
150
  ${t}
131
- <input
132
- class="scb-textfield${this.error ? " has-error-icon" : ""}"
133
- .value=${this.value}
134
- type="${this.type}"
135
- name="${this.name}"
136
- id="${this._inputId}"
137
- ?disabled=${this.disabled}
138
- ?required=${this.required}
139
- aria-invalid=${this.error ? "true" : "false"}
140
- aria-describedby=${i}
141
- />
142
- ${o}
143
- ${e}
144
- <md-ripple></md-ripple>
145
- <md-focus-ring class="input-ring"></md-focus-ring>
151
+ <div class="ripple-wrapper">
152
+ <input
153
+ class="scb-textfield${this.error ? " has-error-icon" : ""}"
154
+ .value=${this.value}
155
+ type="${this.type}"
156
+ name="${this.name}"
157
+ id="${this._inputId}"
158
+ ?disabled=${this.disabled}
159
+ ?required=${this.required}
160
+ aria-invalid=${this.error ? "true" : "false"}
161
+ aria-describedby=${i}
162
+ />
163
+ ${l}
164
+ ${e}
165
+ <md-ripple></md-ripple>
166
+ <md-focus-ring class="input-ring"></md-focus-ring>
167
+ </div>
146
168
  </div>
147
169
  `;
148
170
  }
@@ -155,14 +177,14 @@ ${this.value}</textarea
155
177
  super.firstUpdated(t), this._initialValue = this.value;
156
178
  const e = (i = this.shadowRoot) == null ? void 0 : i.querySelector(".scb-textfield");
157
179
  e && (e.addEventListener("input", () => {
158
- const o = e;
159
- if (this.value = o.value, this._internals) {
160
- const l = this.disabled ? null : this.value;
161
- this._internals.setFormValue(l);
180
+ const l = e;
181
+ if (this.value = l.value, this._internals) {
182
+ const n = this.disabled ? null : this.value;
183
+ this._internals.setFormValue(n);
162
184
  }
163
185
  if (this.pattern) {
164
- const l = new RegExp(this.pattern);
165
- this.error = !l.test(this.value);
186
+ const n = new RegExp(this.pattern);
187
+ this.error = !n.test(this.value);
166
188
  }
167
189
  this.dispatchEvent(new Event("input", { bubbles: !0, composed: !0 })), this.dispatchEvent(
168
190
  new CustomEvent("onValueChanged", {
@@ -176,17 +198,17 @@ ${this.value}</textarea
176
198
  }), e.addEventListener("select", () => {
177
199
  this.dispatchEvent(new Event("select", { bubbles: !0, composed: !0 }));
178
200
  }), e.addEventListener("focus", () => {
179
- this._inputFocused = !0, d(this, n, p).call(this);
201
+ this._inputFocused = !0, d(this, o, p).call(this);
180
202
  }), e.addEventListener("blur", () => {
181
- this._inputFocused = !1, d(this, n, p).call(this);
182
- })), d(this, n, f).call(this);
203
+ this._inputFocused = !1, d(this, o, p).call(this);
204
+ })), d(this, o, f).call(this);
183
205
  }
184
206
  updated(t) {
185
207
  if (super.updated(t), this.toggleAttribute("aria-disabled", this.disabled), this._internals && (t.has("value") || t.has("disabled"))) {
186
208
  const e = this.disabled ? null : this.value;
187
209
  this._internals.setFormValue(e);
188
210
  }
189
- (t.has("spacing") || t.has("spacingTop") || t.has("spacingBottom")) && d(this, n, f).call(this);
211
+ (t.has("spacing") || t.has("spacingTop") || t.has("spacingBottom")) && d(this, o, f).call(this);
190
212
  }
191
213
  // Körs av webbläsaren när formuläret sätter disabled på kontrollen
192
214
  formDisabledCallback(t) {
@@ -216,8 +238,8 @@ ${this.value}</textarea
216
238
  this.required && !t.value ? t.setCustomValidity(this.errorText || "Ogiltig inmatning.") : t.setCustomValidity("");
217
239
  const i = t.reportValidity();
218
240
  this.error = !i;
219
- const o = i ? "" : this.errorText || t.validationMessage || "Ogiltig inmatning.";
220
- return i || (this.errorText = o), this._internals && (i ? this._internals.setValidity({}) : this._internals.setValidity({ customError: !0 }, o, t)), i;
241
+ const l = i ? "" : this.errorText || t.validationMessage || "Ogiltig inmatning.";
242
+ return i || (this.errorText = l), this._internals && (i ? this._internals.setValidity({}) : this._internals.setValidity({ customError: !0 }, l, t)), i;
221
243
  }
222
244
  return !0;
223
245
  }
@@ -243,9 +265,9 @@ ${this.value}</textarea
243
265
  }
244
266
  }
245
267
  };
246
- n = /* @__PURE__ */ new WeakSet();
268
+ o = /* @__PURE__ */ new WeakSet();
247
269
  f = function() {
248
- const t = d(this, n, h).call(this, this.spacing), e = d(this, n, h).call(this, this.spacingTop) ?? t, i = d(this, n, h).call(this, this.spacingBottom) ?? t;
270
+ const t = d(this, o, h).call(this, this.spacing), e = d(this, o, h).call(this, this.spacingTop) ?? t, i = d(this, o, h).call(this, this.spacingBottom) ?? t;
249
271
  e ? this.style.setProperty("--scb-textfield-spacing-block-start", e) : this.style.removeProperty("--scb-textfield-spacing-block-start"), i ? this.style.setProperty("--scb-textfield-spacing-block-end", i) : this.style.removeProperty("--scb-textfield-spacing-block-end");
250
272
  };
251
273
  h = function(t) {
@@ -287,9 +309,6 @@ s.styles = [
287
309
  :host([type='text']) {
288
310
  --scb-textfield-max-width: var(--scb-textfield-text-max-width);
289
311
  }
290
- :host([type='date']) {
291
- --scb-textfield-max-width: var(--scb-textfield-text-max-width);
292
- }
293
312
  :host([type='search']) {
294
313
  --scb-textfield-max-width: var(--scb-textfield-search-max-width);
295
314
  }
@@ -308,6 +327,9 @@ s.styles = [
308
327
  :host([type='textarea']) {
309
328
  --scb-textfield-max-width: var(--scb-textfield-textarea-max-width);
310
329
  }
330
+ :host([type='date']) {
331
+ --scb-textfield-max-width: var(--scb-textfield-text-max-width);
332
+ }
311
333
 
312
334
  :host {
313
335
  display: flex;
@@ -366,6 +388,10 @@ s.styles = [
366
388
  padding-right: var(--spacing-11);
367
389
  }
368
390
 
391
+ :host([type='date']) .scb-textfield {
392
+ padding-right: var(--spacing-11);
393
+ }
394
+
369
395
  md-icon + .scb-textfield {
370
396
  padding-left: var(--spacing-10);
371
397
  }
@@ -477,6 +503,15 @@ s.styles = [
477
503
  height: 100%;
478
504
  display: block;
479
505
  }
506
+
507
+ /* Datumknappen ovanför input/ripple */
508
+ .scb-textfield-datepicker-button {
509
+ position: absolute;
510
+ right: var(--spacing-4);
511
+ top: 50%;
512
+ transform: translateY(-50%);
513
+ z-index: 4;
514
+ }
480
515
  `
481
516
  ];
482
517
  r([
@@ -525,7 +560,7 @@ r([
525
560
  a({ type: String, attribute: "spacing-bottom", reflect: !0 })
526
561
  ], s.prototype, "spacingBottom", 2);
527
562
  r([
528
- a({ type: Boolean })
563
+ g()
529
564
  ], s.prototype, "_showDatepicker", 2);
530
565
  s = r([
531
566
  y("scb-textfield")