bank20baht-ui 0.6.0 → 0.7.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.
@@ -92,6 +92,12 @@ export declare abstract class BahtFieldBase extends BahtElement {
92
92
  /** Emit the user's edit upward (composed so it crosses any boundary). */
93
93
  protected emitInput(value: unknown): void;
94
94
  protected abstract renderControl(): TemplateResult;
95
+ /** True when `field.icon` names a real icon — gates both the icon markup
96
+ * and the control's icon-padding class, so a typo/removed name never
97
+ * leaves the control indented for a glyph that isn't there. */
98
+ protected get hasFieldIcon(): boolean;
99
+ /** Leading icon for text/currency/textarea/dropdown controls (spec: field.icon). */
100
+ protected renderFieldIcon(): TemplateResult | typeof nothing;
95
101
  protected renderLabel(): TemplateResult | typeof nothing;
96
102
  /** Required asterisk, or the "(optional)" marker when the form asks for it. */
97
103
  protected renderLabelMark(): TemplateResult | typeof nothing;
@@ -1,36 +1,37 @@
1
- import { nothing as a, html as h, LitElement as b, ReactiveElement as y } from "lit";
2
- import { property as o } from "lit/decorators.js";
3
- import { t as m } from "../core/i18n.js";
4
- var v = Object.defineProperty, l = (i, t, e, s) => {
1
+ import { nothing as o, html as a, LitElement as y, ReactiveElement as m } from "lit";
2
+ import { property as l } from "lit/decorators.js";
3
+ import { t as v } from "../core/i18n.js";
4
+ import { isIconName as c, renderIcon as C } from "./primitives/icons.js";
5
+ var I = Object.defineProperty, d = (i, e, t, s) => {
5
6
  for (var r = void 0, u = i.length - 1, p; u >= 0; u--)
6
- (p = i[u]) && (r = p(t, e, r) || r);
7
- return r && v(t, e, r), r;
7
+ (p = i[u]) && (r = p(e, t, r) || r);
8
+ return r && I(e, t, r), r;
8
9
  };
9
- function c() {
10
+ function f() {
10
11
  return typeof document < "u" && typeof document.querySelector == "function";
11
12
  }
12
- const C = Symbol.for("bahtui.ssrStash");
13
- function T(i) {
14
- if (i[C]) return !0;
15
- const t = i.firstChild;
16
- return (t == null ? void 0 : t.nodeType) === 8 && t.data.startsWith("lit-part");
13
+ const T = Symbol.for("bahtui.ssrStash");
14
+ function $(i) {
15
+ if (i[T]) return !0;
16
+ const e = i.firstChild;
17
+ return (e == null ? void 0 : e.nodeType) === 8 && e.data.startsWith("lit-part");
17
18
  }
18
- function k(i) {
19
- let t = i.firstChild;
20
- if (!t || t.nodeType !== 8 || !t.data.startsWith("lit-part")) return;
21
- let e = 0;
22
- for (; t; ) {
23
- const s = t.nextSibling;
24
- if (t.nodeType === 8) {
25
- const r = t.data;
26
- r.startsWith("lit-part") ? e += 1 : r.startsWith("/lit-part") && (e -= 1);
19
+ function g(i) {
20
+ let e = i.firstChild;
21
+ if (!e || e.nodeType !== 8 || !e.data.startsWith("lit-part")) return;
22
+ let t = 0;
23
+ for (; e; ) {
24
+ const s = e.nextSibling;
25
+ if (e.nodeType === 8) {
26
+ const r = e.data;
27
+ r.startsWith("lit-part") ? t += 1 : r.startsWith("/lit-part") && (t -= 1);
27
28
  }
28
- if (t.remove(), e === 0) break;
29
- t = s;
29
+ if (e.remove(), t === 0) break;
30
+ e = s;
30
31
  }
31
32
  }
32
- let f = 0;
33
- class $ extends b {
33
+ let b = 0;
34
+ class k extends y {
34
35
  constructor() {
35
36
  super(...arguments), this.uid = 0;
36
37
  }
@@ -48,43 +49,43 @@ class $ extends b {
48
49
  static get observedAttributes() {
49
50
  return [...super.observedAttributes, "defer-hydration"];
50
51
  }
51
- attributeChangedCallback(t, e, s) {
52
- if (t === "defer-hydration") {
52
+ attributeChangedCallback(e, t, s) {
53
+ if (e === "defer-hydration") {
53
54
  s === null && this.isConnected && super.connectedCallback();
54
55
  return;
55
56
  }
56
- super.attributeChangedCallback(t, e, s);
57
+ super.attributeChangedCallback(e, t, s);
57
58
  }
58
59
  connectedCallback() {
59
60
  this.hasAttribute("defer-hydration") || super.connectedCallback();
60
61
  }
61
- update(t) {
62
- const e = !this.hasUpdated, s = globalThis.bahtHydrate, r = e && c() && T(this);
62
+ update(e) {
63
+ const t = !this.hasUpdated, s = globalThis.bahtHydrate, r = t && f() && $(this);
63
64
  if (r)
64
65
  if (s) {
65
66
  const u = this.render();
66
- this.renderOptions.isConnected = this.isConnected, y.prototype.update.call(this, t), s(u, this, this.renderOptions);
67
+ this.renderOptions.isConnected = this.isConnected, m.prototype.update.call(this, e), s(u, this, this.renderOptions);
67
68
  } else
68
- k(this), super.update(t);
69
+ g(this), super.update(e);
69
70
  else
70
- e && c() && this.uid === 0 && (this.uid = ++f), super.update(t);
71
- r && this.uid === 0 && (this.uid = ++f, this.requestUpdate());
71
+ t && f() && this.uid === 0 && (this.uid = ++b), super.update(e);
72
+ r && this.uid === 0 && (this.uid = ++b, this.requestUpdate());
72
73
  }
73
74
  /** Dispatch a bubbling, composed CustomEvent — crosses any light/shadow DOM boundary. */
74
- emit(t, e) {
75
- this.dispatchEvent(new CustomEvent(t, { detail: e, bubbles: !0, composed: !0 }));
75
+ emit(e, t) {
76
+ this.dispatchEvent(new CustomEvent(e, { detail: t, bubbles: !0, composed: !0 }));
76
77
  }
77
78
  }
78
- function O(i, t) {
79
- let e = t;
80
- for (; e.parentNode && e.parentNode !== i; ) e = e.parentNode;
79
+ function E(i, e) {
80
+ let t = e;
81
+ for (; t.parentNode && t.parentNode !== i; ) t = t.parentNode;
81
82
  const s = Array.from(i.childNodes).filter(
82
- (r) => r !== e && r.nodeType !== Node.COMMENT_NODE
83
+ (r) => r !== t && r.nodeType !== Node.COMMENT_NODE
83
84
  );
84
- s.length > 0 && t.append(...s);
85
+ s.length > 0 && e.append(...s);
85
86
  }
86
- var d;
87
- const n = (d = class extends $ {
87
+ var h;
88
+ const n = (h = class extends k {
88
89
  constructor() {
89
90
  super(...arguments), this.value = null, this.disabled = !1, this.readonly = !1, this.required = !1, this.showOptional = !1, this.error = null, this.typed = null, this.onFocusOut = () => this.flushTyped();
90
91
  }
@@ -94,21 +95,21 @@ const n = (d = class extends $ {
94
95
  disconnectedCallback() {
95
96
  this.removeEventListener("focusout", this.onFocusOut), this.flushTyped(), super.disconnectedCallback();
96
97
  }
97
- willUpdate(t) {
98
- var e;
99
- super.willUpdate(t), t.has("value") && ((e = this.typed) != null && e.emitted) && (this.typed = null);
98
+ willUpdate(e) {
99
+ var t;
100
+ super.willUpdate(e), e.has("value") && ((t = this.typed) != null && t.emitted) && (this.typed = null);
100
101
  }
101
102
  get effectiveDebounce() {
102
- return this.debounce ?? d.defaultDebounce;
103
+ return this.debounce ?? h.defaultDebounce;
103
104
  }
104
105
  /** A typed edit: emitted after `debounce` ms of quiet (or at once when 0). */
105
- emitTyped(t) {
106
- const e = this.effectiveDebounce;
107
- if (clearTimeout(this.typedTimer), e <= 0) {
108
- this.typed = null, this.emitInput(t);
106
+ emitTyped(e) {
107
+ const t = this.effectiveDebounce;
108
+ if (clearTimeout(this.typedTimer), t <= 0) {
109
+ this.typed = null, this.emitInput(e);
109
110
  return;
110
111
  }
111
- this.typed = { value: t, emitted: !1 }, this.typedTimer = setTimeout(() => this.flushTyped(), e);
112
+ this.typed = { value: e, emitted: !1 }, this.typedTimer = setTimeout(() => this.flushTyped(), t);
112
113
  }
113
114
  /** Hand a pending typed edit to the host now (blur, disconnect, host reads). Idempotent. */
114
115
  flushTyped() {
@@ -119,21 +120,33 @@ const n = (d = class extends $ {
119
120
  return this.typed ? this.typed.value : this.value;
120
121
  }
121
122
  /** Emit the user's edit upward (composed so it crosses any boundary). */
122
- emitInput(t) {
123
- this.emit("baht-input", { key: this.field.key, value: t });
123
+ emitInput(e) {
124
+ this.emit("baht-input", { key: this.field.key, value: e });
125
+ }
126
+ /** True when `field.icon` names a real icon — gates both the icon markup
127
+ * and the control's icon-padding class, so a typo/removed name never
128
+ * leaves the control indented for a glyph that isn't there. */
129
+ get hasFieldIcon() {
130
+ const e = this.field.icon;
131
+ return e != null && c(e);
132
+ }
133
+ /** Leading icon for text/currency/textarea/dropdown controls (spec: field.icon). */
134
+ renderFieldIcon() {
135
+ const e = this.field.icon;
136
+ return e == null || !c(e) ? o : a`<span class="baht-field-icon" aria-hidden="true">${C(e)}</span>`;
124
137
  }
125
138
  renderLabel() {
126
- return this.field.label ? h`<label class="baht-label" id=${this.labelId} for=${this.controlId}>
139
+ return this.field.label ? a`<label class="baht-label" id=${this.labelId} for=${this.controlId}>
127
140
  ${this.field.label}${this.renderLabelMark()}
128
- </label>` : a;
141
+ </label>` : o;
129
142
  }
130
143
  /** Required asterisk, or the "(optional)" marker when the form asks for it. */
131
144
  renderLabelMark() {
132
- return this.required ? h`<span class="baht-required-mark" aria-hidden="true">*</span>` : this.showOptional ? h`<span class="baht-optional">${m("optional")}</span>` : a;
145
+ return this.required ? a`<span class="baht-required-mark" aria-hidden="true">*</span>` : this.showOptional ? a`<span class="baht-optional">${v("optional")}</span>` : o;
133
146
  }
134
147
  get controlId() {
135
- var t;
136
- return `baht-${((t = this.field) == null ? void 0 : t.key) ?? ""}-${this.uid}`;
148
+ var e;
149
+ return `baht-${((e = this.field) == null ? void 0 : e.key) ?? ""}-${this.uid}`;
137
150
  }
138
151
  get labelId() {
139
152
  return `${this.controlId}-label`;
@@ -146,54 +159,54 @@ const n = (d = class extends $ {
146
159
  }
147
160
  /** id list for the control's aria-describedby: error first, then help. */
148
161
  get describedBy() {
149
- const t = [this.error ? this.errorId : "", this.field.help ? this.helpId : ""].filter(
162
+ const e = [this.error ? this.errorId : "", this.field.help ? this.helpId : ""].filter(
150
163
  Boolean
151
164
  );
152
- return t.length > 0 ? t.join(" ") : a;
165
+ return e.length > 0 ? e.join(" ") : o;
153
166
  }
154
167
  /** 'true' while the field is in error, else absent (styles hook on [aria-invalid]). */
155
168
  get invalid() {
156
- return this.error ? "true" : a;
169
+ return this.error ? "true" : o;
157
170
  }
158
171
  render() {
159
- return this.field ? h`
172
+ return this.field ? a`
160
173
  ${this.renderLabel()}
161
174
  ${this.renderControl()}
162
- ${this.field.help ? h`<div class="baht-help" id=${this.helpId}>${this.field.help}</div>` : a}
163
- ${this.error ? h`<div class="baht-error" id=${this.errorId} role="alert">${this.error}</div>` : a}
164
- ` : a;
175
+ ${this.field.help ? a`<div class="baht-help" id=${this.helpId}>${this.field.help}</div>` : o}
176
+ ${this.error ? a`<div class="baht-error" id=${this.errorId} role="alert">${this.error}</div>` : o}
177
+ ` : o;
165
178
  }
166
- }, d.defaultDebounce = 150, d);
167
- l([
168
- o({ attribute: !1 })
179
+ }, h.defaultDebounce = 150, h);
180
+ d([
181
+ l({ attribute: !1 })
169
182
  ], n.prototype, "field");
170
- l([
171
- o({ attribute: !1 })
183
+ d([
184
+ l({ attribute: !1 })
172
185
  ], n.prototype, "value");
173
- l([
174
- o({ type: Boolean })
186
+ d([
187
+ l({ type: Boolean })
175
188
  ], n.prototype, "disabled");
176
- l([
177
- o({ type: Boolean })
189
+ d([
190
+ l({ type: Boolean })
178
191
  ], n.prototype, "readonly");
179
- l([
180
- o({ type: Boolean })
192
+ d([
193
+ l({ type: Boolean })
181
194
  ], n.prototype, "required");
182
- l([
183
- o({ type: Boolean, attribute: "show-optional" })
195
+ d([
196
+ l({ type: Boolean, attribute: "show-optional" })
184
197
  ], n.prototype, "showOptional");
185
- l([
186
- o({ attribute: !1 })
198
+ d([
199
+ l({ attribute: !1 })
187
200
  ], n.prototype, "error");
188
- l([
189
- o({ type: Number })
201
+ d([
202
+ l({ type: Number })
190
203
  ], n.prototype, "debounce");
191
- let S = n;
204
+ let N = n;
192
205
  export {
193
- $ as BahtElement,
194
- S as BahtFieldBase,
195
- C as SSR_STASH,
196
- O as adoptLightChildren,
197
- c as hasDom,
198
- T as hasSsrMarkup
206
+ k as BahtElement,
207
+ N as BahtFieldBase,
208
+ T as SSR_STASH,
209
+ E as adoptLightChildren,
210
+ f as hasDom,
211
+ $ as hasSsrMarkup
199
212
  };
@@ -1,14 +1,14 @@
1
- import { html as a } from "lit";
1
+ import { html as u } from "lit";
2
2
  import { state as d, customElement as f } from "lit/decorators.js";
3
- import { ifDefined as p } from "lit/directives/if-defined.js";
4
- import { live as m } from "lit/directives/live.js";
5
- import { BahtFieldBase as h } from "../base.js";
6
- var y = Object.defineProperty, b = Object.getOwnPropertyDescriptor, c = (r, e, i, n) => {
7
- for (var t = n > 1 ? void 0 : n ? b(e, i) : e, o = r.length - 1, s; o >= 0; o--)
3
+ import { ifDefined as h } from "lit/directives/if-defined.js";
4
+ import { live as p } from "lit/directives/live.js";
5
+ import { BahtFieldBase as m } from "../base.js";
6
+ var b = Object.defineProperty, y = Object.getOwnPropertyDescriptor, c = (r, e, i, n) => {
7
+ for (var t = n > 1 ? void 0 : n ? y(e, i) : e, o = r.length - 1, s; o >= 0; o--)
8
8
  (s = r[o]) && (t = (n ? s(e, i, t) : s(t)) || t);
9
- return n && t && y(e, i, t), t;
9
+ return n && t && b(e, i, t), t;
10
10
  };
11
- function u(r) {
11
+ function a(r) {
12
12
  const e = r.replace(/,/g, "").trim();
13
13
  if (e === "" || e === "-") return null;
14
14
  const i = Number(e);
@@ -17,40 +17,43 @@ function u(r) {
17
17
  function $(r) {
18
18
  return r.toLocaleString("en-US", { maximumFractionDigits: 2 });
19
19
  }
20
- let l = class extends h {
20
+ let l = class extends m {
21
21
  constructor() {
22
22
  super(...arguments), this.focused = !1;
23
23
  }
24
24
  displayFor(r) {
25
25
  if (r == null || r === "") return "";
26
- const e = typeof r == "number" ? r : u(String(r));
26
+ const e = typeof r == "number" ? r : a(String(r));
27
27
  return e == null ? String(r) : this.focused ? String(e) : $(e);
28
28
  }
29
29
  renderControl() {
30
- return a`<input
31
- class="baht-control baht-control--currency"
32
- id=${this.controlId}
33
- type="text"
34
- inputmode="decimal"
35
- autocomplete="off"
36
- .value=${m(this.displayFor(this.shownValue))}
37
- placeholder=${p(this.field.placeholder)}
38
- ?disabled=${this.disabled}
39
- ?readonly=${this.readonly}
40
- ?required=${this.required}
41
- aria-invalid=${this.invalid}
42
- aria-describedby=${this.describedBy}
43
- @focus=${() => {
30
+ return u`<span class="baht-field-icon-wrap">
31
+ ${this.renderFieldIcon()}
32
+ <input
33
+ class="baht-control baht-control--currency${this.hasFieldIcon ? " baht-control--has-icon" : ""}"
34
+ id=${this.controlId}
35
+ type="text"
36
+ inputmode="decimal"
37
+ autocomplete="off"
38
+ .value=${p(this.displayFor(this.shownValue))}
39
+ placeholder=${h(this.field.placeholder)}
40
+ ?disabled=${this.disabled}
41
+ ?readonly=${this.readonly}
42
+ ?required=${this.required}
43
+ aria-invalid=${this.invalid}
44
+ aria-describedby=${this.describedBy}
45
+ @focus=${() => {
44
46
  this.focused = !0;
45
47
  }}
46
- @blur=${() => {
48
+ @blur=${() => {
47
49
  this.focused = !1;
48
50
  }}
49
- @input=${(r) => {
51
+ @input=${(r) => {
50
52
  const e = r.target.value;
51
- this.emitTyped(e === "" ? null : u(e));
53
+ this.emitTyped(e === "" ? null : a(e));
52
54
  }}
53
- />`;
55
+ />
56
+ </span>`;
54
57
  }
55
58
  };
56
59
  c([
@@ -1,34 +1,37 @@
1
- import { html as h } from "lit";
2
- import { customElement as n } from "lit/decorators.js";
1
+ import { html as d } from "lit";
2
+ import { customElement as h } from "lit/decorators.js";
3
3
  import { ifDefined as r } from "lit/directives/if-defined.js";
4
4
  import { live as p } from "lit/directives/live.js";
5
- import { BahtFieldBase as m } from "../base.js";
6
- var u = Object.getOwnPropertyDescriptor, c = (e, l, d, a) => {
7
- for (var t = a > 1 ? void 0 : a ? u(l, d) : l, i = e.length - 1, s; i >= 0; i--)
5
+ import { BahtFieldBase as c } from "../base.js";
6
+ var m = Object.getOwnPropertyDescriptor, u = (e, l, n, a) => {
7
+ for (var t = a > 1 ? void 0 : a ? m(l, n) : l, i = e.length - 1, s; i >= 0; i--)
8
8
  (s = e[i]) && (t = s(t) || t);
9
9
  return t;
10
10
  };
11
- let o = class extends m {
11
+ let o = class extends c {
12
12
  renderControl() {
13
- return h`<input
14
- class="baht-control baht-control--text"
15
- id=${this.controlId}
16
- type=${this.field.type === "email" ? "email" : this.field.type === "password" ? "password" : "text"}
17
- .value=${p(this.shownValue == null ? "" : String(this.shownValue))}
18
- placeholder=${r(this.field.placeholder)}
19
- maxlength=${r(this.field.max_length)}
20
- autocomplete=${r(this.field.autocomplete)}
21
- ?disabled=${this.disabled}
22
- ?readonly=${this.readonly}
23
- ?required=${this.required}
24
- aria-invalid=${this.invalid}
25
- aria-describedby=${this.describedBy}
26
- @input=${(e) => this.emitTyped(e.target.value)}
27
- />`;
13
+ return d`<span class="baht-field-icon-wrap">
14
+ ${this.renderFieldIcon()}
15
+ <input
16
+ class="baht-control baht-control--text${this.hasFieldIcon ? " baht-control--has-icon" : ""}"
17
+ id=${this.controlId}
18
+ type=${this.field.type === "email" ? "email" : this.field.type === "password" ? "password" : "text"}
19
+ .value=${p(this.shownValue == null ? "" : String(this.shownValue))}
20
+ placeholder=${r(this.field.placeholder)}
21
+ maxlength=${r(this.field.max_length)}
22
+ autocomplete=${r(this.field.autocomplete)}
23
+ ?disabled=${this.disabled}
24
+ ?readonly=${this.readonly}
25
+ ?required=${this.required}
26
+ aria-invalid=${this.invalid}
27
+ aria-describedby=${this.describedBy}
28
+ @input=${(e) => this.emitTyped(e.target.value)}
29
+ />
30
+ </span>`;
28
31
  }
29
32
  };
30
- o = c([
31
- n("baht-input")
33
+ o = u([
34
+ h("baht-input")
32
35
  ], o);
33
36
  export {
34
37
  o as BahtInput
@@ -137,6 +137,7 @@ let n = class extends f {
137
137
  @click=${() => this.toggle()}
138
138
  @keydown=${(s) => this.onKeydown(s)}
139
139
  >
140
+ ${this.renderFieldIcon()}
140
141
  <span class="baht-select-value">${t[e].label}</span>
141
142
  <span class="baht-select-chevron" aria-hidden="true">${m("chevron-down")}</span>
142
143
  </button>
@@ -1,34 +1,37 @@
1
- import { html as h } from "lit";
2
- import { customElement as n } from "lit/decorators.js";
1
+ import { html as n } from "lit";
2
+ import { customElement as d } from "lit/decorators.js";
3
3
  import { ifDefined as a } from "lit/directives/if-defined.js";
4
- import { live as m } from "lit/directives/live.js";
5
- import { BahtFieldBase as p } from "../base.js";
6
- var c = Object.getOwnPropertyDescriptor, u = (e, i, d, l) => {
7
- for (var t = l > 1 ? void 0 : l ? c(i, d) : i, r = e.length - 1, o; r >= 0; r--)
4
+ import { live as c } from "lit/directives/live.js";
5
+ import { BahtFieldBase as m } from "../base.js";
6
+ var p = Object.getOwnPropertyDescriptor, f = (e, i, h, l) => {
7
+ for (var t = l > 1 ? void 0 : l ? p(i, h) : i, r = e.length - 1, o; r >= 0; r--)
8
8
  (o = e[r]) && (t = o(t) || t);
9
9
  return t;
10
10
  };
11
- let s = class extends p {
11
+ let s = class extends m {
12
12
  renderControl() {
13
- return h`<textarea
14
- class="baht-control baht-control--textarea"
15
- id=${this.controlId}
16
- .value=${m(this.shownValue == null ? "" : String(this.shownValue))}
17
- placeholder=${a(this.field.placeholder)}
18
- maxlength=${a(this.field.max_length)}
19
- rows=${this.field.rows ?? 3}
20
- autocomplete=${a(this.field.autocomplete)}
21
- ?disabled=${this.disabled}
22
- ?readonly=${this.readonly}
23
- ?required=${this.required}
24
- aria-invalid=${this.invalid}
25
- aria-describedby=${this.describedBy}
26
- @input=${(e) => this.emitTyped(e.target.value)}
27
- ></textarea>`;
13
+ return n`<span class="baht-field-icon-wrap">
14
+ ${this.renderFieldIcon()}
15
+ <textarea
16
+ class="baht-control baht-control--textarea${this.hasFieldIcon ? " baht-control--has-icon" : ""}"
17
+ id=${this.controlId}
18
+ .value=${c(this.shownValue == null ? "" : String(this.shownValue))}
19
+ placeholder=${a(this.field.placeholder)}
20
+ maxlength=${a(this.field.max_length)}
21
+ rows=${this.field.rows ?? 3}
22
+ autocomplete=${a(this.field.autocomplete)}
23
+ ?disabled=${this.disabled}
24
+ ?readonly=${this.readonly}
25
+ ?required=${this.required}
26
+ aria-invalid=${this.invalid}
27
+ aria-describedby=${this.describedBy}
28
+ @input=${(e) => this.emitTyped(e.target.value)}
29
+ ></textarea>
30
+ </span>`;
28
31
  }
29
32
  };
30
- s = u([
31
- n("baht-textarea")
33
+ s = f([
34
+ d("baht-textarea")
32
35
  ], s);
33
36
  export {
34
37
  s as BahtTextarea
@@ -5,7 +5,11 @@ import { TemplateResult } from 'lit';
5
5
  * `illustrations.ts`, so both files share one look. Free for commercial use,
6
6
  * no attribution required; bundling a curated handful inside a product is
7
7
  * allowed, redistributing the library as an icon collection is not — keep
8
- * this file a short, hand-picked list and never expose it as a picker.
8
+ * this file a short, hand-picked list and never expose it as a picker. A
9
+ * handful of app-domain icons (utensils-crossed, car, house, ...) live here
10
+ * too, for `field.icon` / `FieldOption.icon` cases where a consuming app's
11
+ * concepts overlap with generic ones — still curated per-entry, not a
12
+ * mirror of any app's own icon set.
9
13
  * Licence: https://koboyo.com/icons/license
10
14
  *
11
15
  * Unlike `illustrations.ts` (large spot art with its own aspect ratio) these
@@ -15,7 +19,7 @@ import { TemplateResult } from 'lit';
15
19
  * GENERATED by scripts/koboyo-icons.ts — edit the ENTRIES list there and run
16
20
  * `bun run icons:koboyo-icons`; do not hand-edit the paths.
17
21
  */
18
- export type IconName = 'copy' | 'check' | 'calendar' | 'download' | 'upload' | 'plus' | 'external' | 'close' | 'play' | 'search' | 'sort' | 'chevron-up' | 'chevron-down' | 'chevron-right' | 'more' | 'columns' | 'coin' | 'banknote' | 'bank-building' | 'credit-card' | 'trending-up' | 'trending-down' | 'wallet' | 'piggy-bank' | 'receipt';
22
+ export type IconName = 'copy' | 'check' | 'calendar' | 'download' | 'upload' | 'plus' | 'external' | 'close' | 'play' | 'search' | 'sort' | 'chevron-up' | 'chevron-down' | 'chevron-right' | 'more' | 'columns' | 'coin' | 'banknote' | 'bank-building' | 'credit-card' | 'trending-up' | 'trending-down' | 'wallet' | 'piggy-bank' | 'receipt' | 'utensils-crossed' | 'car' | 'house' | 'celebration-confetti' | 'tag' | 'coffee-cup';
19
23
  /** Render a named icon as an inline SVG that inherits `color`. */
20
24
  export declare function renderIcon(name: IconName): TemplateResult;
21
25
  export declare function isIconName(v: string): v is IconName;
@@ -1,4 +1,4 @@
1
- import { svg as c, html as h } from "lit";
1
+ import { svg as c, html as o } from "lit";
2
2
  const a = {
3
3
  copy: {
4
4
  viewBox: "0 0 144 174",
@@ -99,16 +99,40 @@ const a = {
99
99
  receipt: {
100
100
  viewBox: "0 0 114 179",
101
101
  body: c`<path d="M7.5 11.2c-.3 1.3-.7 35.4-.9 75.8s-.6 75.5-.8 78c-.4 6 1.5 6.2 7.6.9l4.7-4.2 4.3 4.2a18 18 0 0 0 5.5 4.1c.7 0 3.5-1.8 6.1-4s5.2-4 5.7-4 2.7 1.8 4.8 4 4.8 4 6 4c1.1 0 4-2 6.5-4.5l4.4-4.4 4.7 4.4c2.7 2.5 5.5 4.5 6.4 4.5.8 0 3.6-1.8 6-4.1l4.5-4.1 4.9 4.1c2.7 2.3 5.4 4.1 6 4.1s1.8-1.1 2.7-2.5c2.1-3.2 3.1-3.1 6.6.2 2.5 2.4 3 2.5 4.3 1.3 1.1-1.2 1.2-2.9.5-8.5-.5-3.9-1-38.1-1.1-76-.1-38-.4-70.4-.8-72-1-4.8-4.2-4.5-10.7 1.1l-5.5 4.7-4.7-4.6C82.6 11.1 79.5 9 78.4 9s-4 2-6.4 4.5a21 21 0 0 1-5.3 4.5c-.4 0-3-2-5.6-4.5S55.5 9 54.6 9s-4.2 2-7.1 4.5L42.2 18l-5-4.5A20 20 0 0 0 30.8 9c-.8 0-3.4 2-5.8 4.5l-4.5 4.6-4.1-4.6c-4.6-5-8.1-5.9-8.9-2.3M42.4 22c1.1 0 4.1-2.1 6.8-4.6l4.8-4.5 2.8 1.9c1.5 1.1 3.8 3.2 5.1 4.6 3.4 3.6 5.6 3.3 11.3-1.9C76 15 78.5 13 78.9 13s2.7 2 5.1 4.5 5.1 4.5 6 4.5c.8 0 3.9-2.1 6.8-4.6 2.9-2.6 5.5-4.5 5.7-4.2s.5 33.9.7 74.9l.3 74.6-2.3-1.5c-2.1-1.4-2.5-1.3-5.2 1.3l-2.9 2.8-4.5-4.1c-2.5-2.3-5-4.2-5.6-4.2s-3.2 2-5.8 4.4l-4.7 4.4-5-4.4a24 24 0 0 0-6-4.4c-.6 0-3.4 2.1-6.2 4.6l-5.3 4.5-4.8-4.5a23 23 0 0 0-6.1-4.6c-.7 0-3.4 2.1-6.1 4.6l-4.9 4.6-4.9-4.6-4.9-4.6-4.8 3.7q-5 3.8-3.9 1.7c.5-1 1-34.3 1.2-75.3l.3-73.4 4.2 4.1c2.4 2.3 4.8 4.2 5.5 4.2.6 0 3.3-2.1 5.8-4.6l4.7-4.6 4.6 4.6c2.6 2.5 5.5 4.6 6.5 4.6"/><path d="M26.5 48.1q-.6 1 .2 2c.5.5 13.4.8 30.9.7 25.8-.3 29.9-.5 29.9-1.8s-4.1-1.5-30.2-1.8c-21.1-.2-30.4.1-30.8.9m.6 17.8C23 68.5 27.8 69 57 69s34-.5 29.9-3.1A271 271 0 0 0 57 65a271 271 0 0 0-29.9.9M26.5 84c-1.6 2.6 1.4 3 22.1 3 20 0 21.5-.1 21.2-1.8-.3-1.5-2.3-1.7-21.5-2-13.6-.1-21.4.1-21.8.8m0 19c-1.4 2.3 1.1 3 10.9 3 7.4 0 10.7-.4 11.5-1.3q1-1.4.4-2a79 79 0 0 0-22.8.3m45.9.1c-1.1 1.8 1.7 2.9 7.3 2.9 6.1 0 8.3-.7 8.3-2.6 0-1.8-14.5-2-15.6-.3m-46 18c-1.3 2.2 1.5 3 9.7 2.7 7-.3 8.4-.6 8.7-2.1s-.6-1.7-8.7-1.7c-5.4 0-9.3.4-9.7 1.1m46.1-.1q-2.2 3.3 8.1 2.8c5.3-.2 6.9-.6 6.9-1.8s-1.6-1.6-7.2-1.8c-4.5-.2-7.4.1-7.8.8"/>`
102
+ },
103
+ "utensils-crossed": {
104
+ viewBox: "0 0 158 156",
105
+ body: c`<path d="M32.6 8.9c-1.2 1.8.7 4 13.9 16.5C61.2 39.2 64.2 43.5 66 52.3c1 5.1 4.2 10.5 7.5 12.9 3.7 2.7 4.2-1.5.7-5.9a19 19 0 0 1-3.7-8.3c-1.4-9.2-3.9-12.7-19.8-28.2A163 163 0 0 0 34.3 8q-1 0-1.7.9m107.7 2.8c-2.7.5-42.8 38.5-105.5 100-21.7 21.3-22.6 22.7-19.3 29.7a11 11 0 0 0 14.8 5.5 753 753 0 0 0 31.3-30.8l29.1-29.6 2.6 1.8c5.6 3.6 8 2.6 19.5-8.6 21-20.3 27.9-28.2 32.4-37.3 3.7-7.4 4.2-9.5 4.6-16.9.4-8.3.4-8.5-2.6-11.5a13 13 0 0 0-3.9-2.9zm4.8 8.8c1.8 10.3-3.3 21.9-15.9 36C118.2 69 101.2 85 99 85c-.9 0-3.2-1.2-5.1-2.6l-3.4-2.5-31 31.6C32.7 138.8 28.1 143 25.6 143c-3.9 0-6.6-2.6-6.6-6.3 0-2.5 1.6-4.6 8.8-11.7 7.9-7.9 78.5-75.9 102.9-99.3 11.4-10.9 13.4-11.6 14.4-5.2M24.3 17.6c-.4 1.1 3.2 5.4 12.5 14.7 12.5 12.5 13.3 13.1 14.9 11.4 1.7-1.6 1.1-2.4-11.2-14.7-7.1-7.2-13.6-13-14.3-13q-1.2.1-1.9 1.6m-7.2 7.3c-2.4 1.5-.3 4.4 11.8 16.5 8.4 8.4 12.4 11.7 13.5 11.3q1.5-.7 1.6-1.9c0-.7-5.7-7-12.7-14-9.2-9.1-13.2-12.5-14.2-11.9m-8.8 9.7C7.6 36.5 35.6 65.2 41.1 68c1.9 1 6.4 2.4 10 3a26 26 0 0 1 9.7 3.6q5.2 4 5.2-.6c0-2.7-6.2-6.1-14.2-7.6-3.8-.7-8.4-2.2-10.2-3.4A175 175 0 0 1 25 47c-7.3-7.7-13.9-14-14.7-14q-1.2.1-2 1.6"/><path d="M105.1 93.2c-1 1.1 2.8 5.1 19 20.8 18.4 17.8 20.2 19.9 20.2 22.9q0 3.4-2.2 5.3c-5 4-4.5 4.4-37.5-30.5-12.7-13.5-16.1-16.5-17.2-15.6-.8.6-1.4 1.6-1.4 2.1a492 492 0 0 0 22.6 24.9c23.4 24.7 25.5 26.4 31.8 25.2 4.1-.8 8.6-6.6 8.6-11.1a16 16 0 0 0-1.3-5.9A640 640 0 0 0 107.3 92q-1 .1-2.2 1.2"/>`
106
+ },
107
+ car: {
108
+ viewBox: "0 0 203 113",
109
+ body: c`<path d="M89.6 6C71.2 8.3 59.5 16.2 47 34.5l-4.7 7-9.4 2.2c-11.3 2.7-16.3 5.9-19.8 12.8-2.2 4.2-2.6 6.5-3 16-.3 10.8-.2 11.2 2.4 14.3Q16.9 92 26.8 92c4 0 4.3.2 5.8 4 2.6 6.5 10.6 12 17.4 12s14.8-5.5 17.4-12l1.6-4h66l1.6 4a19 19 0 0 0 26.5 9.5 20 20 0 0 0 8.6-10.6c.5-2.8.8-2.9 6.2-3 12.8-.1 16.6-4.2 15.7-16.7a29 29 0 0 0-9.2-20.1c-3.6-2.9-8-4.9-19.4-8.8l-5.5-1.8-5.5-10.4c-8.8-16.3-16.3-22.8-30.7-26.5-7.6-2-24.5-2.8-33.7-1.6m28.4 4.4c16.6 3 24.9 9.7 33.7 27.3l4.9 9.8 9.7 3.2a81 81 0 0 1 13.8 6c3.7 2.4 3.9 2.8 2.1 3.4-1.2.5-2.8 2-3.8 3.4-1.4 2.2-1.5 3.2-.5 6.5 1.3 4.3 2.7 5.4 8.4 6.4 3.3.6 3.7 1 3.7 3.7 0 1.8-.9 3.9-2.5 5.4-2 2.1-3.4 2.5-8.3 2.5h-6l-.6-3.4a20 20 0 0 0-10.5-13c-11.6-4.6-24.4 1.7-26.7 13.1l-.6 3.2-14.7.3c-8 .2-22.7.2-32.7 0l-18-.3-1.1-4.2c-3.1-11.6-15.7-17.1-27-11.6a16 16 0 0 0-9.6 11.7l-1.2 4.4-6.3-.4c-8-.5-10.3-2.6-11-9.7-.4-4.6-.3-5.1 1.5-5.1 4.5 0 8.5-2.3 9.9-5.6 2.7-6.4 1.5-9.4-4.2-10.3l-3.9-.7 3.2-3.1c3-2.9 10.6-5.8 20.8-8 3.4-.7 4.6-1.8 9.1-8.2C61.7 20 72 12.7 87.5 10.1c7.8-1.3 22.2-1.2 30.5.3M22.4 63.7c-1 4.1-2.3 5.3-5.5 5.3-2.4 0-2.9-.4-2.9-2.4 0-4.5 1-5.6 5.1-5.6 3.8 0 3.9.1 3.3 2.7m164.6.8c.6.8 1.6 3 2 5 .8 3.4.7 3.5-2.4 3.5-4.1 0-5.6-1.6-5.6-5.6 0-4.2 3.5-5.9 6-2.9M61.1 78.6a15.3 15.3 0 0 1-2.5 22.7c-9.8 6.4-23.6-.6-23.6-12.1a15 15 0 0 1 26.1-10.6m103.6-.4c3.1 3.1 3.7 4.5 4 9 .6 7-1.8 11.5-7.7 14.5-5.4 2.8-9.4 2.9-14 .4a15 15 0 0 1-2.8-24.7c3.3-3 4.6-3.4 11.1-3.1 5.1.3 6.2.7 9.4 3.9"/><path d="M83 16.5c-3 .9-7.3 2.7-9.6 4-8.2 4.8-20.6 20.8-19.1 24.7.4 1.3 3.2 1.7 14.9 2.1 7.9.3 17.5.5 21.3.4l7-.2.5 18.4c.4 13.5.8 18.5 1.8 18.9S101 81 101 66.6V48h20.8c21.6 0 23.2-.3 23.2-4.3 0-3.2-7.1-15.6-11.5-20.1-6.2-6.4-11.1-7.8-29.5-8.2-11.8-.3-16.8 0-21 1.1M98 31v13H78q-19.9 0-20-1c0-1.7 7.4-11.2 11.8-15.2 5.6-5 9.4-6.8 17.6-8.3C99.1 17.3 98 16.2 98 31m24-10.3c4 1.1 6.5 2.6 9.1 5.4a56 56 0 0 1 9.9 16.8c0 .8-5.9 1.1-19.5 1.1H102V17.8l7.3.7c3.9.3 9.7 1.3 12.7 2.2M46.6 85.6c-1.9 1.9-2 3.5-.3 5.6q3.3 4 6.7.8c1.1-1.1 2-2.6 2-3.4 0-2-2.8-4.6-5-4.6-1 0-2.6.7-3.4 1.6M51 89q0 .9-1 1a1 1 0 0 1-1-1q.1-1 1-1t1 1m99.5-3.4c-3.4 3.4-.1 8.3 4.7 7.1 3.1-.8 4.1-3.8 2.1-6.6-1.7-2.5-4.6-2.7-6.8-.5M155 89q0 .9-.9 1-1-.1-1.6-1-.4-1 .9-1 1.5 0 1.6 1"/>`
110
+ },
111
+ house: {
112
+ viewBox: "0 0 174 168",
113
+ body: c`<path d="M116.2 9.2c-1.8 1.8-1.5 12.8.4 14.9q1.5 1.6 1.2 6.7l-.3 5-15.3-12.4C90.5 14 86.1 11 84 11c-2.3 0-5.4 2.3-14.2 10.3L40 48C11.8 73.1 8 76.9 8 80.1c0 3.6 4.4 7.2 8.2 6.7l2.8-.5.2 36.6.3 36.6 66.6.3 66.6.2.6-9.7c.4-5.4.7-22 .7-36.9V86.3l2.6.5c5 .9 10.5-4.8 9-9.5-.3-1-6-6.3-12.6-11.8l-12-10V40.2c0-12.3.3-15.6 1.5-16.8 1.8-1.9 2.1-12.4.3-14.2a70 70 0 0 0-26.6 0m22.8 7.3V21h-19v-9h19zm-36 13.2C149.5 68 160.5 77.4 160.8 79c.2.9-.4 2.3-1.2 3-2 1.6-2.6 1.2-18.2-11.6C96.2 33.1 84.8 24 84 24c-.5 0-7.3 5.7-15.2 12.7-36.9 33-48.5 43.1-50.9 44.7-2.5 1.5-2.8 1.6-4.3.1a7 7 0 0 1-1.6-2c0-.3 21.5-19.8 57.9-52.4A67 67 0 0 1 84.4 16c1.2.1 9.4 6.1 18.6 13.7m33 8.5c0 12.4-.1 13-1.7 11.6l-7-5.8-5.3-4.3V25h14zm-31 7.9 30.8 25.3L149 82.3v73.6H77v-28.2c0-20.7-.3-28.6-1.2-29.5-1.8-1.8-30.2-1.7-31.7.1q-1.1 1.4-1.3 29.3l-.3 27.9H24V82.1l2.9-2.3C28.4 78.5 42 66.6 57 53.2 81.2 31.5 84.4 29 85.9 30.3zm-32.6 82.6-.1 26.6-12.4.1-12.4.1-.3-26.8L47 102h25.5z"/><path d="M95.2 89.2c-1.8 1.8-1.7 36.2.2 37.7.9.8 7 1.1 19.7.9l18.4-.3.3-18.9c.2-14.5-.1-19.1-1-19.8-2.2-1.3-36.2-1-37.6.4M112 99v7H99V92h13zm18 0v7h-14V92h14zm-18 17.5c0 5.7-.2 6.5-1.9 6.5l-6.5.6-4.6.7V110h13zm18-.2c0 3.5-.2 6.6-.4 6.8s-3.4.2-7 .1l-6.6-.4V110h14zm-63.9 11c-1.5 1.5-1.4 4.4.2 4.9 2.1.8 3.7-.3 3.7-2.7 0-2.6-2.2-3.9-3.9-2.2"/>`
114
+ },
115
+ "celebration-confetti": {
116
+ viewBox: "0 0 177 200",
117
+ body: c`<path d="M109.6 10.9c-2 2.2-1.4 4.1 1.3 4.1 1 0 3.1 1 4.6 2.1 2.2 1.8 2.9 2 3.6.8q.8-1.4.9-2.5c0-.6.9-2.3 2.1-3.8l2-2.6h-3.8q-3.6 0-2.5.8c1.1.8.7 4.2-.5 4.2-1.7 0-4.1-2.3-3.7-3.5.9-2.2-2-1.9-4 .4m57.4 2.7c-1 3.1-1 3.9.4 5.2 1.5 1.5 1.6 1.2 1.6-3.6a18 18 0 0 0-.4-5.2c-.3 0-1 1.6-1.6 3.6m-94.9 9.5c-2.3 1.6-4.1 3.4-4.1 4 0 2.3 4.4 8.9 6 8.9 2 0 9-4.8 9-6.1 0-1.8-4.2-8.8-5.6-9.3-.7-.3-3.1.8-5.3 2.5m6.3 4.2c.9 1.5.7 2.1-.8 3.3q-4.3 3.2-5.2-1.2c-1.1-4.3 3.6-5.9 6-2.1m66.5-3.6-.3 6c-.1 6-2.7 9.5-8.5 11.4-8.1 2.7-10.2 5.4-11.2 14.7-.8 7.8-3.1 10.6-10.1 12.2-6.6 1.6-10.3 5-12.3 11.1-1 2.8-1.5 5.3-1.1 5.6 1.2 1.2 3.3-.7 3.9-3.4q1.4-7.5 10.7-10c8.3-2.3 10.9-5.3 12-13.7 1-8.5 2.7-11 8.8-13 2.7-.9 6.2-3 7.8-4.7 2.6-2.7 2.9-3.7 2.9-9.6q0-6.6-1.2-7t-1.4.4M98.1 38.4c.1 7.7-1.7 10.5-10.2 15.1-8.3 4.6-10.9 8-10.9 14.3 0 4.7 2.6 10.2 4.7 10.2 1.7 0 1.6-1.1-.2-4.6-3.3-6.4-.6-12.8 7.1-16.3q13.3-6.3 13.4-17.5 0-6.6-2.6-6.6c-.9 0-1.3 1.5-1.3 5.4m68.6 16.4c-2.3 2.5-2.1 7.5.2 9.6 1.8 1.6 1.9 1.5 1.9-4.9a32 32 0 0 0-.3-6.5zM48.6 80.2c-2 1.8-5.7 11-15.4 37.8-22.3 61.5-25.5 71.1-24.4 72.2 1 1 40.7-19.5 81.2-42 19-10.5 20-11.3 20-16.5a25 25 0 0 0-2-8.6c-7.3-15.9-30.6-37.6-46.6-43.2-7-2.5-9.7-2.4-12.8.3m20.2 7.1c20.4 11.6 42.9 40.3 37.1 47.3-4.6 5.5-30.7-10.8-44.2-27.7C51.6 94.3 47 82.8 51.8 81.8c3.3-.7 9.8 1.3 17 5.5m-13.4 17.1c10.4 14.4 29.1 29.6 40.9 33.1l4 1.2-14.3 7.8-14.2 7.8-4.7-2.3a74 74 0 0 1-29.2-26.5l-2.3-4.3 4.9-13.4L46.2 92c.9-2.4 1-2.3 2.9 1.9 1.1 2.4 3.9 7.1 6.3 10.5m-13.2 32.8a78 78 0 0 0 21.2 16.5l4.9 2.5-13.8 7.4-13.9 7.4-4.3-2.6a41 41 0 0 1-12.2-11.1c-.8-1.6 1.7-9.5 9.4-30.2q.5-1.7 2.7 2a72 72 0 0 0 6 8.1m-8.4 33.6 3.4 2-11.9 6.5c-6.5 3.6-12 6.4-12.2 6.2s1.5-5.5 3.8-11.8 4.1-12 4.1-12.8c0-.7 2.1.8 4.8 3.3s6.2 5.5 8 6.6m107.2-87c-1.4.9-4.4 3.6-6.6 5.9-3.9 4.1-4.5 4.3-9.9 4.3a25 25 0 0 0-9 1.6c-4.2 2-7.2 6.1-5.6 7.7.9.9 1.7.5 3.4-1.5q4.6-5.4 10-4.4 7.6 1.5 14.5-5.9c4.9-5.4 8.1-6.8 13.9-5.9 3.4.5 4.3.3 4.3-.9 0-3-11-3.7-15-.9m25.1 18.8-2.4 1.7 2.4 2c2.4 1.9 2.4 1.9 2.7-.2.2-1.2.2-2.8 0-3.6-.3-1.4-.6-1.3-2.7.1m-30.6 11.3-4 .6.3 5c.4 6.5 1.5 7.5 7.5 6.6 2.6-.4 5-1 5.3-1.4s.2-2.9-.3-5.9c-.9-5.8-1.3-6.1-8.8-4.9m5.5 6.1c0 2.7-.3 3-3 3s-3-.3-3-3 .3-3 3-3 3 .3 3 3"/>`
118
+ },
119
+ tag: {
120
+ viewBox: "0 0 151 153",
121
+ body: c`<path d="M85 9c-4.7.3-9.4 1.1-10.5 1.7A1738 1738 0 0 0 9.3 78.2 21 21 0 0 0 9 91.6c.6 1.4 11.5 13.5 24.3 26.7C56.8 142.6 60.9 146 67.5 146c6.8 0 10.5-3.2 41.9-35.7 17-17.6 31.6-33.3 32.5-34.9 1.4-2.5 1.6-7 1.6-30.1 0-26-.1-27.3-2.1-30a30 30 0 0 0-5.4-5.1c-3.2-2.1-4.1-2.2-22.9-2-10.8 0-23.4.4-28.1.8m47.6 5.5c6.1 2.5 6.6 5.4 6.2 32.4-.3 17.6-.7 24.2-1.7 26.1-2.5 4.5-62.5 65.2-65.8 66.6-6.4 2.7-7.7 1.8-33.3-24.2C13.1 90 11.6 88 13.5 81.8c.4-1.2 8.5-10.2 17.9-19.8l30.2-31c7.3-7.5 14-14.2 14.9-15 3.4-2.8 50-4.1 56.1-1.5"/><path d="M107.3 28.6a13 13 0 0 0-6.3 10.6c0 3 3.3 8.4 6.1 9.9 3.2 1.7 9.1 1.5 12.1-.5 1.5-1 3.4-3.3 4.3-5.3 4.6-9.6-6.5-19.7-16.2-14.7M117 34c4 4 1.5 11-4.1 11-2.8 0-6.9-3.9-6.9-6.7 0-2.1 4.6-6.3 7-6.3a7 7 0 0 1 4 2"/>`
122
+ },
123
+ "coffee-cup": {
124
+ viewBox: "0 0 179 138",
125
+ body: c`<path d="M52 7c-14.8 1.8-30.3 6.7-36.8 11.7-6 4.5-7.2 7.6-7.2 18.4 0 12.3 1.5 27.5 4 41 7.8 41.3 24.3 55.3 63.5 53.6 7.1-.3 15.4-1.2 18.2-2q18-5.1 25.5-18.3c2.6-4.8 3.4-5.4 6.2-5.4 9.7 0 23.6-6.1 31.6-13.9 16.7-16.3 18.7-42.7 4.2-53.8-5.7-4.3-11.1-5.7-19.9-4.9l-7.3.6v-3.8q0-15-33-21.7C92 6.6 62.5 5.8 52 7m43 5.5c15.5 2.3 25.6 6 31.3 11.3 4 3.8 3.3 6.8-2.5 10.6-2.5 1.7-2.8 1.6-7.6-.8-21.7-11-68.2-11.1-89.5-.1A32 32 0 0 1 21 36c-2.1 0-7-5.3-7-7.5 0-6.8 16.6-13.8 39.5-16.8 7.8-1 32.9-.6 41.5.8m5.8 20.4c4.5 1.1 9.7 2.8 11.5 3.8l3.2 1.7-4.5 1.3c-6.9 2.2-32.6 3.6-52 2.9-16.6-.6-31-2.8-31-4.6 0-1.1 11-4.6 18.5-5.9l8.5-1.5c1.4-.3 10.4-.3 20-.1 13.6.2 19.3.8 25.8 2.4M14.5 37c.4.6 2.9 2.2 5.7 3.6 13.6 6.9 43.2 10.8 65.3 8.6 15.8-1.6 29.6-5.1 38.1-9.6l6.6-3.5-.6 9.7a400 400 0 0 1-2.7 23.2c-6.3 44.8-19.1 58.2-55.4 58.2a73 73 0 0 1-30.9-5.4q-13.7-7-21-32.2c-2.9-10-6.4-33-6.8-45.4-.3-7.6.2-9.6 1.7-7.2m140.4 3c8.4 4.2 11.6 11.1 10.9 23.1-1 17-12.9 31-30.7 36.3-3 .9-6.7 1.6-8.1 1.6h-2.7l1.6-5c.9-2.7 2.1-5 2.8-5 3.4 0 12.6-4.5 16.7-8.2 12-10.4 13.8-28 3.5-33.4a17 17 0 0 0-12.3-.4c-2.6.9-2.6.9-2.6-4 0-6.1 1.2-6.9 10.3-7 4.8 0 7.9.6 10.6 2m-6.1 15.7c4.8 5.3 1.9 15.8-6.5 23.4-4.1 3.6-11.9 7.6-12.9 6.6-.2-.1.6-5.2 1.6-11.2a126 126 0 0 0 2.3-19.5l4.2-1.4c4.9-1.8 8.3-1.2 11.3 2.1"/>`
102
126
  }
103
127
  };
104
- function m(l) {
105
- const { viewBox: o, body: d } = a[l];
106
- return h`<svg class="baht-icon" viewBox=${o} fill="currentColor" aria-hidden="true">${d}</svg>`;
128
+ function v(l) {
129
+ const { viewBox: m, body: h } = a[l];
130
+ return o`<svg class="baht-icon" viewBox=${m} fill="currentColor" aria-hidden="true">${h}</svg>`;
107
131
  }
108
132
  function t(l) {
109
133
  return Object.prototype.hasOwnProperty.call(a, l);
110
134
  }
111
135
  export {
112
136
  t as isIconName,
113
- m as renderIcon
137
+ v as renderIcon
114
138
  };
@@ -34,6 +34,12 @@ export interface FieldDescriptor {
34
34
  key: string;
35
35
  label?: string;
36
36
  placeholder?: string;
37
+ /**
38
+ * Leading icon inside the control (text/email/password/currency/textarea)
39
+ * or before the value (dropdown) — icon name from the curated set (see
40
+ * icons.ts). Unrecognized names render no icon (no layout shift).
41
+ */
42
+ icon?: string;
37
43
  help?: string;
38
44
  autocomplete?: string;
39
45
  width?: FieldWidth;