aeico-components 0.1.4 → 0.1.6

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 (299) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/dist/chunks/action-button.cjs +296 -0
  4. package/dist/chunks/action-button.cjs.map +1 -0
  5. package/dist/chunks/action-button.js +297 -0
  6. package/dist/chunks/action-button.js.map +1 -0
  7. package/dist/chunks/alert.cjs +4 -4
  8. package/dist/chunks/alert.cjs.map +1 -1
  9. package/dist/chunks/alert.js +5 -5
  10. package/dist/chunks/alert.js.map +1 -1
  11. package/dist/chunks/badge.cjs +1 -1
  12. package/dist/chunks/badge.cjs.map +1 -1
  13. package/dist/chunks/badge.js +2 -2
  14. package/dist/chunks/badge.js.map +1 -1
  15. package/dist/chunks/breadcrumb-item.cjs +2 -2
  16. package/dist/chunks/breadcrumb-item.cjs.map +1 -1
  17. package/dist/chunks/breadcrumb-item.js +3 -3
  18. package/dist/chunks/breadcrumb-item.js.map +1 -1
  19. package/dist/chunks/button-group.cjs +1 -1
  20. package/dist/chunks/button-group.cjs.map +1 -1
  21. package/dist/chunks/button-group.js +2 -2
  22. package/dist/chunks/button-group.js.map +1 -1
  23. package/dist/chunks/button.cjs +12 -15
  24. package/dist/chunks/button.cjs.map +1 -1
  25. package/dist/chunks/button.js +13 -16
  26. package/dist/chunks/button.js.map +1 -1
  27. package/dist/chunks/card.cjs +1 -1
  28. package/dist/chunks/card.cjs.map +1 -1
  29. package/dist/chunks/card.js +2 -2
  30. package/dist/chunks/card.js.map +1 -1
  31. package/dist/chunks/checkbox.cjs +18 -5
  32. package/dist/chunks/checkbox.cjs.map +1 -1
  33. package/dist/chunks/checkbox.js +18 -5
  34. package/dist/chunks/checkbox.js.map +1 -1
  35. package/dist/chunks/copy-button.cjs +168 -0
  36. package/dist/chunks/copy-button.cjs.map +1 -0
  37. package/dist/chunks/copy-button.js +169 -0
  38. package/dist/chunks/copy-button.js.map +1 -0
  39. package/dist/chunks/detail.cjs +7 -4
  40. package/dist/chunks/detail.cjs.map +1 -1
  41. package/dist/chunks/detail.js +8 -5
  42. package/dist/chunks/detail.js.map +1 -1
  43. package/dist/chunks/dialog.cjs +1 -1
  44. package/dist/chunks/dialog.cjs.map +1 -1
  45. package/dist/chunks/dialog.js +2 -2
  46. package/dist/chunks/dialog.js.map +1 -1
  47. package/dist/chunks/divider.cjs +1 -1
  48. package/dist/chunks/divider.cjs.map +1 -1
  49. package/dist/chunks/divider.js +2 -2
  50. package/dist/chunks/divider.js.map +1 -1
  51. package/dist/chunks/drawer.cjs +180 -0
  52. package/dist/chunks/drawer.cjs.map +1 -0
  53. package/dist/chunks/drawer.js +181 -0
  54. package/dist/chunks/drawer.js.map +1 -0
  55. package/dist/chunks/dropdown-button.cjs +2 -2
  56. package/dist/chunks/dropdown-button.cjs.map +1 -1
  57. package/dist/chunks/dropdown-button.js +6 -6
  58. package/dist/chunks/dropdown-button.js.map +1 -1
  59. package/dist/chunks/icon.cjs +31 -1
  60. package/dist/chunks/icon.cjs.map +1 -1
  61. package/dist/chunks/icon.js +32 -2
  62. package/dist/chunks/icon.js.map +1 -1
  63. package/dist/chunks/menu.cjs +396 -0
  64. package/dist/chunks/menu.cjs.map +1 -0
  65. package/dist/chunks/menu.js +397 -0
  66. package/dist/chunks/menu.js.map +1 -0
  67. package/dist/chunks/navbar.cjs +2 -3
  68. package/dist/chunks/navbar.cjs.map +1 -1
  69. package/dist/chunks/navbar.js +3 -4
  70. package/dist/chunks/navbar.js.map +1 -1
  71. package/dist/chunks/pagination.cjs +475 -0
  72. package/dist/chunks/pagination.cjs.map +1 -0
  73. package/dist/chunks/pagination.js +476 -0
  74. package/dist/chunks/pagination.js.map +1 -0
  75. package/dist/chunks/progress-bar.cjs +101 -0
  76. package/dist/chunks/progress-bar.cjs.map +1 -0
  77. package/dist/chunks/progress-bar.js +102 -0
  78. package/dist/chunks/progress-bar.js.map +1 -0
  79. package/dist/chunks/radio.cjs +11 -7
  80. package/dist/chunks/radio.cjs.map +1 -1
  81. package/dist/chunks/radio.js +11 -7
  82. package/dist/chunks/radio.js.map +1 -1
  83. package/dist/chunks/select.cjs +97 -66
  84. package/dist/chunks/select.cjs.map +1 -1
  85. package/dist/chunks/select.js +97 -66
  86. package/dist/chunks/select.js.map +1 -1
  87. package/dist/chunks/slider.cjs +9 -46
  88. package/dist/chunks/slider.cjs.map +1 -1
  89. package/dist/chunks/slider.js +9 -46
  90. package/dist/chunks/slider.js.map +1 -1
  91. package/dist/chunks/spinner.cjs +102 -0
  92. package/dist/chunks/spinner.cjs.map +1 -0
  93. package/dist/chunks/spinner.js +103 -0
  94. package/dist/chunks/spinner.js.map +1 -0
  95. package/dist/chunks/switch.cjs +110 -16
  96. package/dist/chunks/switch.cjs.map +1 -1
  97. package/dist/chunks/switch.js +111 -17
  98. package/dist/chunks/switch.js.map +1 -1
  99. package/dist/chunks/tab-panel.cjs +6 -7
  100. package/dist/chunks/tab-panel.cjs.map +1 -1
  101. package/dist/chunks/tab-panel.js +7 -8
  102. package/dist/chunks/tab-panel.js.map +1 -1
  103. package/dist/chunks/tag.cjs +1 -1
  104. package/dist/chunks/tag.cjs.map +1 -1
  105. package/dist/chunks/tag.js +2 -2
  106. package/dist/chunks/tag.js.map +1 -1
  107. package/dist/chunks/text-input.cjs +11 -16
  108. package/dist/chunks/text-input.cjs.map +1 -1
  109. package/dist/chunks/text-input.js +11 -16
  110. package/dist/chunks/text-input.js.map +1 -1
  111. package/dist/chunks/textarea.cjs +137 -0
  112. package/dist/chunks/textarea.cjs.map +1 -0
  113. package/dist/chunks/textarea.js +138 -0
  114. package/dist/chunks/textarea.js.map +1 -0
  115. package/dist/chunks/tooltip.cjs +293 -0
  116. package/dist/chunks/tooltip.cjs.map +1 -0
  117. package/dist/chunks/tooltip.js +294 -0
  118. package/dist/chunks/tooltip.js.map +1 -0
  119. package/dist/chunks/tree.cjs +468 -0
  120. package/dist/chunks/tree.cjs.map +1 -0
  121. package/dist/chunks/tree.js +469 -0
  122. package/dist/chunks/tree.js.map +1 -0
  123. package/dist/chunks/variables.cjs +2 -2
  124. package/dist/chunks/variables.js +2 -2
  125. package/dist/copy-button.cjs +6 -0
  126. package/dist/copy-button.cjs.map +1 -0
  127. package/dist/copy-button.js +6 -0
  128. package/dist/copy-button.js.map +1 -0
  129. package/dist/drawer.cjs +6 -0
  130. package/dist/drawer.cjs.map +1 -0
  131. package/dist/drawer.js +6 -0
  132. package/dist/drawer.js.map +1 -0
  133. package/dist/dropdown.js +4 -4
  134. package/dist/index.cjs +186 -0
  135. package/dist/index.cjs.map +1 -1
  136. package/dist/index.js +201 -15
  137. package/dist/index.js.map +1 -1
  138. package/dist/menu.cjs +6 -0
  139. package/dist/menu.cjs.map +1 -0
  140. package/dist/menu.js +6 -0
  141. package/dist/menu.js.map +1 -0
  142. package/dist/pagination.cjs +6 -0
  143. package/dist/pagination.cjs.map +1 -0
  144. package/dist/pagination.js +6 -0
  145. package/dist/pagination.js.map +1 -0
  146. package/dist/progress-bar.cjs +6 -0
  147. package/dist/progress-bar.cjs.map +1 -0
  148. package/dist/progress-bar.js +6 -0
  149. package/dist/progress-bar.js.map +1 -0
  150. package/dist/select.cjs +1 -1
  151. package/dist/select.cjs.map +1 -1
  152. package/dist/select.js +2 -2
  153. package/dist/select.js.map +1 -1
  154. package/dist/spinner.cjs +6 -0
  155. package/dist/spinner.cjs.map +1 -0
  156. package/dist/spinner.js +6 -0
  157. package/dist/spinner.js.map +1 -0
  158. package/dist/textarea.cjs +5 -0
  159. package/dist/textarea.cjs.map +1 -0
  160. package/dist/textarea.js +5 -0
  161. package/dist/textarea.js.map +1 -0
  162. package/dist/tooltip.cjs +6 -0
  163. package/dist/tooltip.cjs.map +1 -0
  164. package/dist/tooltip.js +6 -0
  165. package/dist/tooltip.js.map +1 -0
  166. package/dist/tree.cjs +6 -0
  167. package/dist/tree.cjs.map +1 -0
  168. package/dist/tree.js +6 -0
  169. package/dist/tree.js.map +1 -0
  170. package/dist/types/aeico-field.d.ts +57 -5
  171. package/dist/types/alert/alert.d.ts +1 -0
  172. package/dist/types/button/button.d.ts +2 -1
  173. package/dist/types/checkbox/checkbox.d.ts +5 -5
  174. package/dist/types/copy-button/copy-button.d.ts +32 -0
  175. package/dist/types/copy-button/defines.d.ts +1 -0
  176. package/dist/types/copy-button/index.d.ts +3 -0
  177. package/dist/types/detail/defines.d.ts +1 -0
  178. package/dist/types/detail/detail.d.ts +3 -1
  179. package/dist/types/detail/index.d.ts +1 -1
  180. package/dist/types/detail-group/detail-group.d.ts +39 -0
  181. package/dist/types/detail-group/index.d.ts +2 -0
  182. package/dist/types/drawer/defines.d.ts +1 -0
  183. package/dist/types/drawer/drawer.d.ts +31 -0
  184. package/dist/types/drawer/index.d.ts +3 -0
  185. package/dist/types/icon/built-in-icons.d.ts +1 -0
  186. package/dist/types/icon/icon.d.ts +1 -0
  187. package/dist/types/icon/registry.d.ts +8 -0
  188. package/dist/types/index.d.ts +19 -0
  189. package/dist/types/menu/defines.d.ts +15 -0
  190. package/dist/types/menu/index.d.ts +5 -0
  191. package/dist/types/menu/menu-item.d.ts +63 -0
  192. package/dist/types/menu/menu.d.ts +34 -0
  193. package/dist/types/number-input/index.d.ts +2 -0
  194. package/dist/types/number-input/number-input.d.ts +35 -0
  195. package/dist/types/pagination/defines.d.ts +2 -0
  196. package/dist/types/pagination/index.d.ts +3 -0
  197. package/dist/types/pagination/pagination.d.ts +77 -0
  198. package/dist/types/progress-bar/defines.d.ts +1 -0
  199. package/dist/types/progress-bar/index.d.ts +3 -0
  200. package/dist/types/progress-bar/progress-bar.d.ts +37 -0
  201. package/dist/types/radio-group/radio-group.d.ts +1 -1
  202. package/dist/types/select/select.d.ts +3 -3
  203. package/dist/types/spinner/defines.d.ts +3 -0
  204. package/dist/types/spinner/index.d.ts +3 -0
  205. package/dist/types/spinner/spinner.d.ts +35 -0
  206. package/dist/types/switch/defines.d.ts +1 -0
  207. package/dist/types/switch/switch.d.ts +13 -9
  208. package/dist/types/text-input/text-input.d.ts +0 -4
  209. package/dist/types/textarea/index.d.ts +1 -0
  210. package/dist/types/textarea/textarea.d.ts +26 -0
  211. package/dist/types/tooltip/defines.d.ts +2 -0
  212. package/dist/types/tooltip/index.d.ts +4 -0
  213. package/dist/types/tooltip/tooltip.d.ts +48 -0
  214. package/dist/types/tree/defines.d.ts +23 -0
  215. package/dist/types/tree/index.d.ts +5 -0
  216. package/dist/types/tree/tree-item.d.ts +54 -0
  217. package/dist/types/tree/tree.d.ts +64 -0
  218. package/package.json +6 -6
  219. package/src/aeico-field.ts +154 -15
  220. package/src/alert/alert.ts +3 -2
  221. package/src/button/button.ts +11 -13
  222. package/src/checkbox/checkbox.ts +21 -6
  223. package/src/copy-button/copy-button.ts +146 -0
  224. package/src/copy-button/defines.ts +5 -0
  225. package/src/copy-button/index.ts +3 -0
  226. package/src/detail/defines.ts +1 -0
  227. package/src/detail/detail.ts +5 -1
  228. package/src/detail/index.ts +1 -1
  229. package/src/detail-group/detail-group.ts +104 -0
  230. package/src/detail-group/index.ts +2 -0
  231. package/src/drawer/defines.ts +1 -0
  232. package/src/drawer/drawer.ts +157 -0
  233. package/src/drawer/index.ts +3 -0
  234. package/src/icon/built-in-icons.ts +21 -0
  235. package/src/icon/icon.ts +1 -0
  236. package/src/icon/registry.ts +22 -0
  237. package/src/index.ts +32 -0
  238. package/src/menu/defines.ts +17 -0
  239. package/src/menu/index.ts +5 -0
  240. package/src/menu/menu-item.ts +315 -0
  241. package/src/menu/menu.ts +81 -0
  242. package/src/navbar/navbar.ts +1 -3
  243. package/src/number-input/index.ts +2 -0
  244. package/src/number-input/number-input.ts +137 -0
  245. package/src/pagination/defines.ts +2 -0
  246. package/src/pagination/index.ts +3 -0
  247. package/src/pagination/pagination.ts +310 -0
  248. package/src/progress-bar/defines.ts +8 -0
  249. package/src/progress-bar/index.ts +3 -0
  250. package/src/progress-bar/progress-bar.ts +80 -0
  251. package/src/radio-group/radio-group.ts +12 -5
  252. package/src/select/select.ts +112 -71
  253. package/src/slider/slider.ts +9 -2
  254. package/src/spinner/defines.ts +12 -0
  255. package/src/spinner/index.ts +3 -0
  256. package/src/spinner/spinner.ts +81 -0
  257. package/src/styles/components/action-button.css +37 -0
  258. package/src/styles/components/checkbox.css +4 -26
  259. package/src/styles/components/copy-button.css +119 -0
  260. package/src/styles/components/detail-group.css +10 -0
  261. package/src/styles/components/detail.css +10 -1
  262. package/src/styles/components/drawer.css +161 -0
  263. package/src/styles/components/field-label.css +120 -0
  264. package/src/styles/components/menu-item.css +168 -0
  265. package/src/styles/components/menu.css +17 -0
  266. package/src/styles/components/number-input.css +167 -0
  267. package/src/styles/components/pagination.css +205 -0
  268. package/src/styles/components/progress-bar.css +44 -0
  269. package/src/styles/components/radio-group.css +0 -23
  270. package/src/styles/components/select.css +12 -39
  271. package/src/styles/components/slider.css +0 -42
  272. package/src/styles/components/spinner.css +80 -0
  273. package/src/styles/components/switch.css +68 -19
  274. package/src/styles/components/tab-panel.css +1 -1
  275. package/src/styles/components/tabs.css +1 -0
  276. package/src/styles/components/text-input.css +7 -45
  277. package/src/styles/components/textarea.css +75 -0
  278. package/src/styles/components/tooltip.css +103 -0
  279. package/src/styles/components/tree-item.css +152 -0
  280. package/src/styles/components/tree.css +10 -0
  281. package/src/styles/layout.css +457 -25
  282. package/src/switch/defines.ts +1 -0
  283. package/src/switch/switch.ts +65 -16
  284. package/src/tabs/tab.ts +1 -1
  285. package/src/tabs/tabs.ts +1 -2
  286. package/src/text-input/text-input.ts +10 -15
  287. package/src/textarea/index.ts +1 -0
  288. package/src/textarea/textarea.ts +107 -0
  289. package/src/tooltip/defines.ts +11 -0
  290. package/src/tooltip/index.ts +4 -0
  291. package/src/tooltip/tooltip.ts +183 -0
  292. package/src/tree/defines.ts +26 -0
  293. package/src/tree/index.ts +5 -0
  294. package/src/tree/tree-item.ts +258 -0
  295. package/src/tree/tree.ts +237 -0
  296. package/dist/chunks/aeico-field.cjs +0 -179
  297. package/dist/chunks/aeico-field.cjs.map +0 -1
  298. package/dist/chunks/aeico-field.js +0 -180
  299. package/dist/chunks/aeico-field.js.map +0 -1
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Eowl
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
Binary file
@@ -0,0 +1,296 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
4
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
5
+ const aeico = require("aeico");
6
+ const aeicoComponent = require("./aeico-component.cjs");
7
+ const _AeicoField = class _AeicoField extends aeicoComponent.AeicoComponent {
8
+ constructor() {
9
+ super();
10
+ __publicField(this, "_fieldId");
11
+ /**
12
+ * The underlying form control element (input, select, etc.)
13
+ * Subclasses should set this to their specific element
14
+ */
15
+ __publicField(this, "fieldElement", null);
16
+ __publicField(this, "resetBtn", null);
17
+ __publicField(this, "clearBtn", null);
18
+ __publicField(this, "boundOnChange", () => this.setValue(this.getValue(), { silent: false, action: "change" }));
19
+ __publicField(this, "boundOnReset", () => this.onReset());
20
+ __publicField(this, "boundOnClear", () => this.onClear());
21
+ this._fieldId = `ae-field-${++_AeicoField._fieldIdCounter}`;
22
+ }
23
+ /**
24
+ * Lifecycle: Component connected to DOM
25
+ */
26
+ connectedCallback() {
27
+ super.connectedCallback();
28
+ }
29
+ /**
30
+ * Lifecycle: Component disconnected from DOM
31
+ */
32
+ disconnectedCallback() {
33
+ super.disconnectedCallback();
34
+ }
35
+ /**
36
+ * Render action buttons (clear/reset) using this.builder.
37
+ * Must be called from within a build() callback.
38
+ */
39
+ renderActionButtons(force = false) {
40
+ const style = this.actionButtonStyle || "integrated";
41
+ const hasActions = force || this.clearable || this.resettable;
42
+ if (hasActions && style === "integrated") {
43
+ aeico.tags.div({ className: "action-controls" }, () => {
44
+ this.renderClearButton(force);
45
+ this.renderResetButton(force);
46
+ });
47
+ } else {
48
+ this.renderClearButton(force);
49
+ this.renderResetButton(force);
50
+ }
51
+ }
52
+ renderResetButton(force = false) {
53
+ const { button } = aeico.tags;
54
+ const style = this.actionButtonStyle || "integrated";
55
+ if (force || this.resettable) {
56
+ const className = style === "integrated" ? "reset-btn action-btn" : "reset-btn";
57
+ this.resetBtn = button({
58
+ className,
59
+ textContent: this.resetText || "↺",
60
+ title: this.resetTitle || "↺",
61
+ "@click": this.boundOnReset
62
+ });
63
+ }
64
+ }
65
+ renderClearButton(force = false) {
66
+ const { button } = aeico.tags;
67
+ const style = this.actionButtonStyle || "integrated";
68
+ if (force || this.clearable) {
69
+ const className = style === "integrated" ? "clear-btn action-btn" : "clear-btn";
70
+ this.clearBtn = button({
71
+ className,
72
+ textContent: this.clearText || "✕",
73
+ title: this.clearTitle || "✕",
74
+ "@click": this.boundOnClear
75
+ });
76
+ }
77
+ }
78
+ /**
79
+ * Returns a stable unique ID for this field instance,
80
+ * used to associate <label htmlFor> with the underlying input.
81
+ */
82
+ getFieldId() {
83
+ return this._fieldId;
84
+ }
85
+ /**
86
+ * Renders a <label> element when the `label` prop is set.
87
+ * Call this as the first statement inside the render() html() callback.
88
+ * @param fieldId - The id to set on the underlying form control element (pass to input via id prop)
89
+ */
90
+ renderLabel(fieldId) {
91
+ if (!this.label) return;
92
+ const { span } = aeico.tags;
93
+ aeico.tags.label({ id: `${fieldId}-label`, className: "field-label", for: fieldId }, () => {
94
+ span({ textContent: this.label });
95
+ if (this.required) {
96
+ span({ className: "field-required", "aria-hidden": "true", textContent: " *" });
97
+ }
98
+ });
99
+ }
100
+ /**
101
+ * Renders helper text below the field. Hidden when `error` is set.
102
+ * Call this after the field-body div in render().
103
+ */
104
+ renderHelperText() {
105
+ if (!this.helperText || this.error) return;
106
+ const { span } = aeico.tags;
107
+ span({ className: "field-helper", textContent: this.helperText });
108
+ }
109
+ /**
110
+ * Renders an error message below the field when `error` is set.
111
+ * Call this after renderHelperText() in render().
112
+ */
113
+ renderError() {
114
+ if (!this.error) return;
115
+ const { span } = aeico.tags;
116
+ span({ className: "field-error", textContent: this.error });
117
+ }
118
+ /**
119
+ * Watcher for disabled property
120
+ */
121
+ onDisabledChanged(newValue) {
122
+ if (this.fieldElement) {
123
+ this.fieldElement.disabled = Boolean(newValue);
124
+ }
125
+ }
126
+ /**
127
+ * Watcher for error property — syncs aria-invalid on the field element
128
+ */
129
+ onErrorChanged(newValue) {
130
+ if (this.fieldElement) {
131
+ if (newValue) {
132
+ this.fieldElement.setAttribute("aria-invalid", "true");
133
+ } else {
134
+ this.fieldElement.removeAttribute("aria-invalid");
135
+ }
136
+ }
137
+ }
138
+ /**
139
+ * Lifecycle: called after every render update.
140
+ * Keeps aria-invalid on fieldElement in sync regardless of watcher timing.
141
+ */
142
+ onUpdated(_changedProps) {
143
+ if (!this.fieldElement) return;
144
+ if (this.error) {
145
+ this.fieldElement.setAttribute("aria-invalid", "true");
146
+ } else {
147
+ this.fieldElement.removeAttribute("aria-invalid");
148
+ }
149
+ }
150
+ /**
151
+ * Returns true if the field passes constraint validation.
152
+ * Delegates to the underlying fieldElement when available;
153
+ * falls back to a manual required-check otherwise.
154
+ */
155
+ checkValidity() {
156
+ if (this.fieldElement) {
157
+ return this.fieldElement.checkValidity();
158
+ }
159
+ if (this.required) {
160
+ const v = this.value;
161
+ return v !== void 0 && v !== "" && v !== null;
162
+ }
163
+ return true;
164
+ }
165
+ /**
166
+ * Reports validity, showing the browser's built-in validation UI when possible.
167
+ */
168
+ reportValidity() {
169
+ if (this.fieldElement) {
170
+ return this.fieldElement.reportValidity();
171
+ }
172
+ return this.checkValidity();
173
+ }
174
+ /**
175
+ * Render the field component
176
+ * Override in subclass to provide custom rendering
177
+ */
178
+ render() {
179
+ }
180
+ /**
181
+ * Get current value from the field element
182
+ * Default implementation returns the value property of fieldElement
183
+ * Override in subclasses if needed (e.g., checkbox uses checked instead of value)
184
+ *
185
+ * @returns Current field value
186
+ */
187
+ getValue() {
188
+ var _a;
189
+ return ((_a = this.fieldElement) == null ? void 0 : _a.value) || "";
190
+ }
191
+ /**
192
+ * Write value to the underlying UI element and sync props
193
+ * Subclasses must override this to update their specific UI element
194
+ *
195
+ * @param _value New value to write to the element
196
+ */
197
+ writeValue(_value) {
198
+ }
199
+ /**
200
+ * Get event payload for change events
201
+ * Override in subclasses to customize event data (e.g., { checked, oldChecked } for checkbox)
202
+ *
203
+ * @param value New value
204
+ * @param oldValue Previous value
205
+ * @param action Action type
206
+ * @returns Event payload object
207
+ */
208
+ getEventPayload(value, oldValue, action) {
209
+ return { value, oldValue, action };
210
+ }
211
+ /**
212
+ * Update field value programmatically (internal method)
213
+ * Subclasses should provide type-safe public wrappers (e.g., change() method)
214
+ *
215
+ * @param value New value
216
+ * @param options.silent If true, won't emit change event (default: true)
217
+ * @param options.action Action type for the event (default: 'change')
218
+ */
219
+ setValue(value, options) {
220
+ const oldValue = this.getValue();
221
+ this.value = value;
222
+ this.writeValue(value);
223
+ if ((options == null ? void 0 : options.silent) === false) {
224
+ const payload = this.getEventPayload(value, oldValue, options.action || "change");
225
+ this.emit("change", { detail: payload });
226
+ }
227
+ }
228
+ /**
229
+ * Reset field to specified value or default value
230
+ *
231
+ * @param value Value to reset to, defaults to defaultValue prop
232
+ * @param options.silent If false, will emit reset event (default: true)
233
+ */
234
+ reset(value, options) {
235
+ const resetValue = value !== void 0 ? value : this.defaultValue;
236
+ this.setValue(resetValue, { ...options, action: "reset" });
237
+ }
238
+ /**
239
+ * Clear the field value
240
+ *
241
+ * @param options.silent If false, will emit clear event (default: true)
242
+ */
243
+ clear(options) {
244
+ this.setValue("", { ...options, action: "clear" });
245
+ }
246
+ /**
247
+ * Handle clear button click
248
+ * Clears the field and dispatches event
249
+ */
250
+ onClear() {
251
+ this.clear({ silent: false });
252
+ }
253
+ /**
254
+ * Handle reset button click
255
+ * Resets to default value and dispatches event
256
+ */
257
+ onReset() {
258
+ this.reset(void 0, { silent: false });
259
+ }
260
+ };
261
+ /**
262
+ * Define base field properties (extends AeicoElement properties)
263
+ */
264
+ __publicField(_AeicoField, "props", {
265
+ value: { type: String },
266
+ defaultValue: { type: String },
267
+ resettable: { type: Boolean },
268
+ resetText: { type: String },
269
+ resetTitle: { type: String },
270
+ clearable: { type: Boolean },
271
+ clearText: { type: String },
272
+ clearTitle: { type: String },
273
+ actionButtonStyle: { type: String },
274
+ size: { type: String },
275
+ disabled: { type: Boolean },
276
+ label: { type: String },
277
+ labelPlacement: { type: String },
278
+ required: { type: Boolean },
279
+ helperText: { type: String },
280
+ error: { type: String }
281
+ });
282
+ /**
283
+ * Property watchers
284
+ */
285
+ __publicField(_AeicoField, "watchers", {
286
+ disabled: "onDisabledChanged",
287
+ error: "onErrorChanged"
288
+ });
289
+ __publicField(_AeicoField, "_fieldIdCounter", 0);
290
+ let AeicoField = _AeicoField;
291
+ const fieldLabelCSS = ':host {\n --field-label-gap: 4px;\n --field-label-col-gap: 8px;\n --field-label-width: 100px;\n --field-label-font-size: 0.875em;\n --field-label-color: inherit;\n --field-required-color: var(--red, #dc3545);\n --field-helper-color: var(--color-text-muted, #6e6e6e);\n --field-error-color: var(--red, #dc3545);\n}\n\n:host([label]) {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--field-label-gap);\n}\n\n:host([label][label-placement="left"]) {\n display: grid;\n grid-template-columns: var(--field-label-width) 1fr;\n column-gap: var(--field-label-col-gap);\n row-gap: var(--field-label-gap);\n align-items: start;\n}\n\n:host([label][label-placement="left"]) .field-label {\n align-self: center;\n}\n\n:host([label][label-placement="left"]) .field-helper,\n:host([label][label-placement="left"]) .field-error {\n grid-column: 2;\n}\n\n.field-label {\n font-size: var(--field-label-font-size);\n color: var(--field-label-color);\n user-select: none;\n line-height: 1.4;\n}\n\n.field-required {\n color: var(--field-required-color);\n margin-left: 2px;\n}\n\n.field-helper {\n font-size: 0.8em;\n color: var(--field-helper-color);\n line-height: 1.4;\n}\n\n.field-error {\n font-size: 0.8em;\n color: var(--field-error-color);\n line-height: 1.4;\n}\n\n/* Action controls container (integrated style) */\n.action-controls {\n display: flex;\n flex-direction: row;\n align-items: stretch;\n margin-left: calc(-1 * var(--field-action-gap, 4px) - 1px);\n border: var(--field-action-border-width, 1px) solid var(--field-action-border-color, var(--border-subtle));\n border-radius: 0 var(--field-action-border-radius, 2px) var(--field-action-border-radius, 2px) 0;\n overflow: hidden;\n flex-shrink: 0;\n transition: border-color 0.12s;\n background: var(--field-action-bg, var(--surface-base));\n position: relative;\n z-index: 1;\n align-self: stretch;\n}\n\n.action-controls .action-btn {\n border: none;\n background: transparent;\n color: var(--field-action-color, var(--color-text-muted));\n font-size: 0.875em;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 0.5em;\n transition: background 0.12s;\n}\n\n.action-controls .action-btn:hover:not(:disabled) {\n background: var(--field-action-bg-hover, var(--surface-raised));\n}\n\n.action-controls .action-btn:active:not(:disabled) {\n background: var(--field-action-bg-focus, var(--surface-raised));\n}\n\n.action-controls .action-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.action-controls .action-btn + .action-btn {\n border-left: var(--field-action-border-width, 1px) solid var(--field-action-border-color, var(--border-subtle));\n}\n\n.input-container:has(input:focus) ~ .action-controls,\n.input-container:has(input:focus) .action-controls,\n.container:has(.trigger.open) ~ .action-controls,\n.container:has(.trigger.open) .action-controls {\n border-color: var(--field-action-border-color-focus, var(--border-focus));\n}\n\n.input-container:has(input:hover:not(:focus)) ~ .action-controls,\n.input-container:has(input:hover:not(:focus)) .action-controls,\n.container:has(.trigger:hover:not(.disabled)) ~ .action-controls,\n.container:has(.trigger:hover:not(.disabled)) .action-controls {\n border-color: var(--field-action-border-color-hover, var(--border-default));\n}\n';
292
+ const actionButtonCSS = "/* Action button base styles — shared by clear-btn and reset-btn (standalone mode) */\n.clear-btn:not(.action-btn),\n.reset-btn:not(.action-btn) {\n width: 1.333em;\n height: 1.333em;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n line-height: 1;\n}\n\n.clear-btn:not(.action-btn) {\n border-radius: var(--clear-btn-border-radius);\n background: var(--clear-btn-bg);\n color: var(--clear-btn-color);\n transition: var(--clear-btn-transition);\n}\n\n.reset-btn:not(.action-btn) {\n border-radius: var(--reset-btn-border-radius);\n background: var(--reset-btn-bg);\n color: var(--reset-btn-color);\n transition: var(--reset-btn-transition);\n}\n\n.clear-btn:not(.action-btn):hover {\n background: var(--clear-btn-bg-hover);\n color: var(--clear-btn-color-hover);\n}\n\n.reset-btn:not(.action-btn):hover {\n background: var(--reset-btn-bg-hover);\n color: var(--reset-btn-color-hover);\n}\n";
293
+ exports.AeicoField = AeicoField;
294
+ exports.actionButtonCSS = actionButtonCSS;
295
+ exports.fieldLabelCSS = fieldLabelCSS;
296
+ //# sourceMappingURL=action-button.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-button.cjs","sources":["../../src/aeico-field.ts"],"sourcesContent":["import type { InferProps, Props, Watchers } from 'aeico';\nimport { tags } from 'aeico';\nimport AeicoComponent from './aeico-component';\n\nexport type FieldAction = 'clear' | 'reset' | 'change';\nexport type FieldElement = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\nexport type ActionButtonStyle = 'standalone' | 'integrated';\n\n/**\n * Base class for form field components\n *\n * Provides common functionality for field components including:\n * - Theme support\n * - i18n integration (via Localizable mixin)\n * - Reset button management\n * - Value management\n * - Common configuration handling\n */\nclass AeicoField<TValue = string> extends AeicoComponent {\n /**\n * Define base field properties (extends AeicoElement properties)\n */\n static props: Props = {\n value: { type: String },\n defaultValue: { type: String },\n resettable: { type: Boolean },\n resetText: { type: String },\n resetTitle: { type: String },\n clearable: { type: Boolean },\n clearText: { type: String },\n clearTitle: { type: String },\n actionButtonStyle: { type: String },\n size: { type: String },\n disabled: { type: Boolean },\n label: { type: String },\n labelPlacement: { type: String },\n required: { type: Boolean },\n helperText: { type: String },\n error: { type: String },\n };\n\n /**\n * Property watchers\n */\n static watchers: Watchers = {\n disabled: 'onDisabledChanged',\n error: 'onErrorChanged',\n };\n\n private static _fieldIdCounter = 0;\n private readonly _fieldId: string;\n\n constructor() {\n super();\n this._fieldId = `ae-field-${++AeicoField._fieldIdCounter}`;\n }\n\n /**\n * The underlying form control element (input, select, etc.)\n * Subclasses should set this to their specific element\n */\n protected fieldElement: FieldElement | null = null;\n\n protected resetBtn: HTMLButtonElement | null = null;\n protected clearBtn: HTMLButtonElement | null = null;\n\n protected readonly boundOnChange = () =>\n this.setValue(this.getValue(), { silent: false, action: 'change' });\n\n protected readonly boundOnReset = () => this.onReset();\n protected readonly boundOnClear = () => this.onClear();\n\n // Declare reactive properties for TypeScript\n declare value?: TValue;\n declare defaultValue?: TValue | string;\n declare resettable?: boolean;\n declare resetText?: string;\n declare resetTitle?: string;\n declare clearable?: boolean;\n declare clearText?: string;\n declare clearTitle?: string;\n declare actionButtonStyle?: ActionButtonStyle;\n declare size?: string;\n declare disabled?: boolean;\n declare label?: string;\n declare labelPlacement?: 'top' | 'left';\n declare required?: boolean;\n declare helperText?: string;\n declare error?: string;\n\n /**\n * Lifecycle: Component connected to DOM\n */\n connectedCallback() {\n super.connectedCallback();\n }\n\n /**\n * Lifecycle: Component disconnected from DOM\n */\n disconnectedCallback() {\n super.disconnectedCallback();\n }\n\n /**\n * Render action buttons (clear/reset) using this.builder.\n * Must be called from within a build() callback.\n */\n protected renderActionButtons(force: boolean = false) {\n const style = this.actionButtonStyle || 'integrated';\n const hasActions = force || this.clearable || this.resettable;\n\n if (hasActions && style === 'integrated') {\n tags.div({ className: 'action-controls' }, () => {\n this.renderClearButton(force);\n this.renderResetButton(force);\n });\n } else {\n this.renderClearButton(force);\n this.renderResetButton(force);\n }\n }\n\n protected renderResetButton(force: boolean = false) {\n const { button } = tags;\n const style = this.actionButtonStyle || 'integrated';\n\n if (force || this.resettable) {\n const className = style === 'integrated' ? 'reset-btn action-btn' : 'reset-btn';\n this.resetBtn = button({\n className,\n textContent: this.resetText || '↺',\n title: this.resetTitle || '↺',\n '@click': this.boundOnReset,\n });\n }\n }\n\n protected renderClearButton(force: boolean = false) {\n const { button } = tags;\n const style = this.actionButtonStyle || 'integrated';\n\n if (force || this.clearable) {\n const className = style === 'integrated' ? 'clear-btn action-btn' : 'clear-btn';\n this.clearBtn = button({\n className,\n textContent: this.clearText || '✕',\n title: this.clearTitle || '✕',\n '@click': this.boundOnClear,\n });\n }\n }\n\n /**\n * Returns a stable unique ID for this field instance,\n * used to associate <label htmlFor> with the underlying input.\n */\n protected getFieldId(): string {\n return this._fieldId;\n }\n\n /**\n * Renders a <label> element when the `label` prop is set.\n * Call this as the first statement inside the render() html() callback.\n * @param fieldId - The id to set on the underlying form control element (pass to input via id prop)\n */\n protected renderLabel(fieldId: string): void {\n if (!this.label) return;\n const { span } = tags;\n tags.label({ id: `${fieldId}-label`, className: 'field-label', for: fieldId }, () => {\n span({ textContent: this.label! });\n if (this.required) {\n span({ className: 'field-required', 'aria-hidden': 'true', textContent: ' *' });\n }\n });\n }\n\n /**\n * Renders helper text below the field. Hidden when `error` is set.\n * Call this after the field-body div in render().\n */\n protected renderHelperText(): void {\n if (!this.helperText || this.error) return;\n const { span } = tags;\n span({ className: 'field-helper', textContent: this.helperText });\n }\n\n /**\n * Renders an error message below the field when `error` is set.\n * Call this after renderHelperText() in render().\n */\n protected renderError(): void {\n if (!this.error) return;\n const { span } = tags;\n span({ className: 'field-error', textContent: this.error });\n }\n\n /**\n * Watcher for disabled property\n */\n protected onDisabledChanged(newValue: boolean) {\n if (this.fieldElement) {\n (this.fieldElement as HTMLInputElement | HTMLSelectElement).disabled = Boolean(newValue);\n }\n }\n\n /**\n * Watcher for error property — syncs aria-invalid on the field element\n */\n protected onErrorChanged(newValue: string | undefined): void {\n if (this.fieldElement) {\n if (newValue) {\n this.fieldElement.setAttribute('aria-invalid', 'true');\n } else {\n this.fieldElement.removeAttribute('aria-invalid');\n }\n }\n }\n\n /**\n * Lifecycle: called after every render update.\n * Keeps aria-invalid on fieldElement in sync regardless of watcher timing.\n */\n protected onUpdated(_changedProps: Map<string, unknown>): void {\n if (!this.fieldElement) return;\n if (this.error) {\n this.fieldElement.setAttribute('aria-invalid', 'true');\n } else {\n this.fieldElement.removeAttribute('aria-invalid');\n }\n }\n\n /**\n * Returns true if the field passes constraint validation.\n * Delegates to the underlying fieldElement when available;\n * falls back to a manual required-check otherwise.\n */\n public checkValidity(): boolean {\n if (this.fieldElement) {\n return this.fieldElement.checkValidity();\n }\n if (this.required) {\n const v = this.value;\n return v !== undefined && v !== '' && v !== null;\n }\n return true;\n }\n\n /**\n * Reports validity, showing the browser's built-in validation UI when possible.\n */\n public reportValidity(): boolean {\n if (this.fieldElement) {\n return this.fieldElement.reportValidity();\n }\n return this.checkValidity();\n }\n\n /**\n * Render the field component\n * Override in subclass to provide custom rendering\n */\n render(): void {\n // Default implementation - subclasses can override\n }\n\n /**\n * Get current value from the field element\n * Default implementation returns the value property of fieldElement\n * Override in subclasses if needed (e.g., checkbox uses checked instead of value)\n *\n * @returns Current field value\n */\n protected getValue(): TValue {\n return (this.fieldElement?.value || '') as TValue;\n }\n\n /**\n * Write value to the underlying UI element and sync props\n * Subclasses must override this to update their specific UI element\n *\n * @param _value New value to write to the element\n */\n protected writeValue(_value: TValue): void {\n // Base implementation - subclasses override\n }\n\n /**\n * Get event payload for change events\n * Override in subclasses to customize event data (e.g., { checked, oldChecked } for checkbox)\n *\n * @param value New value\n * @param oldValue Previous value\n * @param action Action type\n * @returns Event payload object\n */\n protected getEventPayload(\n value: TValue,\n oldValue: TValue,\n action: FieldAction,\n ): Record<string, unknown> {\n return { value, oldValue, action };\n }\n\n /**\n * Update field value programmatically (internal method)\n * Subclasses should provide type-safe public wrappers (e.g., change() method)\n *\n * @param value New value\n * @param options.silent If true, won't emit change event (default: true)\n * @param options.action Action type for the event (default: 'change')\n */\n protected setValue(value: TValue, options?: { silent?: boolean; action?: FieldAction }): void {\n const oldValue = this.getValue();\n\n // Update property value\n this.value = value;\n\n // Write to UI element (DOM only)\n this.writeValue(value);\n\n // Emit event if not silent\n if (options?.silent === false) {\n const payload = this.getEventPayload(value, oldValue, options.action || 'change');\n this.emit('change', { detail: payload });\n }\n }\n\n /**\n * Reset field to specified value or default value\n *\n * @param value Value to reset to, defaults to defaultValue prop\n * @param options.silent If false, will emit reset event (default: true)\n */\n public reset(value?: TValue, options?: { silent?: boolean }): void {\n const resetValue = value !== undefined ? value : this.defaultValue;\n this.setValue(resetValue as TValue, { ...options, action: 'reset' });\n }\n\n /**\n * Clear the field value\n *\n * @param options.silent If false, will emit clear event (default: true)\n */\n public clear(options?: { silent?: boolean }): void {\n this.setValue('' as TValue, { ...options, action: 'clear' });\n }\n\n /**\n * Handle clear button click\n * Clears the field and dispatches event\n */\n protected onClear(): void {\n this.clear({ silent: false });\n }\n\n /**\n * Handle reset button click\n * Resets to default value and dispatches event\n */\n protected onReset(): void {\n this.reset(undefined, { silent: false });\n }\n}\n\nexport default AeicoField;\nexport type AeicoFieldProps = InferProps<typeof AeicoField>;\n"],"names":["AeicoComponent","tags"],"mappings":"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"}
@@ -0,0 +1,297 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { tags } from "aeico";
5
+ import { A as AeicoComponent } from "./aeico-component.js";
6
+ const _AeicoField = class _AeicoField extends AeicoComponent {
7
+ constructor() {
8
+ super();
9
+ __publicField(this, "_fieldId");
10
+ /**
11
+ * The underlying form control element (input, select, etc.)
12
+ * Subclasses should set this to their specific element
13
+ */
14
+ __publicField(this, "fieldElement", null);
15
+ __publicField(this, "resetBtn", null);
16
+ __publicField(this, "clearBtn", null);
17
+ __publicField(this, "boundOnChange", () => this.setValue(this.getValue(), { silent: false, action: "change" }));
18
+ __publicField(this, "boundOnReset", () => this.onReset());
19
+ __publicField(this, "boundOnClear", () => this.onClear());
20
+ this._fieldId = `ae-field-${++_AeicoField._fieldIdCounter}`;
21
+ }
22
+ /**
23
+ * Lifecycle: Component connected to DOM
24
+ */
25
+ connectedCallback() {
26
+ super.connectedCallback();
27
+ }
28
+ /**
29
+ * Lifecycle: Component disconnected from DOM
30
+ */
31
+ disconnectedCallback() {
32
+ super.disconnectedCallback();
33
+ }
34
+ /**
35
+ * Render action buttons (clear/reset) using this.builder.
36
+ * Must be called from within a build() callback.
37
+ */
38
+ renderActionButtons(force = false) {
39
+ const style = this.actionButtonStyle || "integrated";
40
+ const hasActions = force || this.clearable || this.resettable;
41
+ if (hasActions && style === "integrated") {
42
+ tags.div({ className: "action-controls" }, () => {
43
+ this.renderClearButton(force);
44
+ this.renderResetButton(force);
45
+ });
46
+ } else {
47
+ this.renderClearButton(force);
48
+ this.renderResetButton(force);
49
+ }
50
+ }
51
+ renderResetButton(force = false) {
52
+ const { button } = tags;
53
+ const style = this.actionButtonStyle || "integrated";
54
+ if (force || this.resettable) {
55
+ const className = style === "integrated" ? "reset-btn action-btn" : "reset-btn";
56
+ this.resetBtn = button({
57
+ className,
58
+ textContent: this.resetText || "↺",
59
+ title: this.resetTitle || "↺",
60
+ "@click": this.boundOnReset
61
+ });
62
+ }
63
+ }
64
+ renderClearButton(force = false) {
65
+ const { button } = tags;
66
+ const style = this.actionButtonStyle || "integrated";
67
+ if (force || this.clearable) {
68
+ const className = style === "integrated" ? "clear-btn action-btn" : "clear-btn";
69
+ this.clearBtn = button({
70
+ className,
71
+ textContent: this.clearText || "✕",
72
+ title: this.clearTitle || "✕",
73
+ "@click": this.boundOnClear
74
+ });
75
+ }
76
+ }
77
+ /**
78
+ * Returns a stable unique ID for this field instance,
79
+ * used to associate <label htmlFor> with the underlying input.
80
+ */
81
+ getFieldId() {
82
+ return this._fieldId;
83
+ }
84
+ /**
85
+ * Renders a <label> element when the `label` prop is set.
86
+ * Call this as the first statement inside the render() html() callback.
87
+ * @param fieldId - The id to set on the underlying form control element (pass to input via id prop)
88
+ */
89
+ renderLabel(fieldId) {
90
+ if (!this.label) return;
91
+ const { span } = tags;
92
+ tags.label({ id: `${fieldId}-label`, className: "field-label", for: fieldId }, () => {
93
+ span({ textContent: this.label });
94
+ if (this.required) {
95
+ span({ className: "field-required", "aria-hidden": "true", textContent: " *" });
96
+ }
97
+ });
98
+ }
99
+ /**
100
+ * Renders helper text below the field. Hidden when `error` is set.
101
+ * Call this after the field-body div in render().
102
+ */
103
+ renderHelperText() {
104
+ if (!this.helperText || this.error) return;
105
+ const { span } = tags;
106
+ span({ className: "field-helper", textContent: this.helperText });
107
+ }
108
+ /**
109
+ * Renders an error message below the field when `error` is set.
110
+ * Call this after renderHelperText() in render().
111
+ */
112
+ renderError() {
113
+ if (!this.error) return;
114
+ const { span } = tags;
115
+ span({ className: "field-error", textContent: this.error });
116
+ }
117
+ /**
118
+ * Watcher for disabled property
119
+ */
120
+ onDisabledChanged(newValue) {
121
+ if (this.fieldElement) {
122
+ this.fieldElement.disabled = Boolean(newValue);
123
+ }
124
+ }
125
+ /**
126
+ * Watcher for error property — syncs aria-invalid on the field element
127
+ */
128
+ onErrorChanged(newValue) {
129
+ if (this.fieldElement) {
130
+ if (newValue) {
131
+ this.fieldElement.setAttribute("aria-invalid", "true");
132
+ } else {
133
+ this.fieldElement.removeAttribute("aria-invalid");
134
+ }
135
+ }
136
+ }
137
+ /**
138
+ * Lifecycle: called after every render update.
139
+ * Keeps aria-invalid on fieldElement in sync regardless of watcher timing.
140
+ */
141
+ onUpdated(_changedProps) {
142
+ if (!this.fieldElement) return;
143
+ if (this.error) {
144
+ this.fieldElement.setAttribute("aria-invalid", "true");
145
+ } else {
146
+ this.fieldElement.removeAttribute("aria-invalid");
147
+ }
148
+ }
149
+ /**
150
+ * Returns true if the field passes constraint validation.
151
+ * Delegates to the underlying fieldElement when available;
152
+ * falls back to a manual required-check otherwise.
153
+ */
154
+ checkValidity() {
155
+ if (this.fieldElement) {
156
+ return this.fieldElement.checkValidity();
157
+ }
158
+ if (this.required) {
159
+ const v = this.value;
160
+ return v !== void 0 && v !== "" && v !== null;
161
+ }
162
+ return true;
163
+ }
164
+ /**
165
+ * Reports validity, showing the browser's built-in validation UI when possible.
166
+ */
167
+ reportValidity() {
168
+ if (this.fieldElement) {
169
+ return this.fieldElement.reportValidity();
170
+ }
171
+ return this.checkValidity();
172
+ }
173
+ /**
174
+ * Render the field component
175
+ * Override in subclass to provide custom rendering
176
+ */
177
+ render() {
178
+ }
179
+ /**
180
+ * Get current value from the field element
181
+ * Default implementation returns the value property of fieldElement
182
+ * Override in subclasses if needed (e.g., checkbox uses checked instead of value)
183
+ *
184
+ * @returns Current field value
185
+ */
186
+ getValue() {
187
+ var _a;
188
+ return ((_a = this.fieldElement) == null ? void 0 : _a.value) || "";
189
+ }
190
+ /**
191
+ * Write value to the underlying UI element and sync props
192
+ * Subclasses must override this to update their specific UI element
193
+ *
194
+ * @param _value New value to write to the element
195
+ */
196
+ writeValue(_value) {
197
+ }
198
+ /**
199
+ * Get event payload for change events
200
+ * Override in subclasses to customize event data (e.g., { checked, oldChecked } for checkbox)
201
+ *
202
+ * @param value New value
203
+ * @param oldValue Previous value
204
+ * @param action Action type
205
+ * @returns Event payload object
206
+ */
207
+ getEventPayload(value, oldValue, action) {
208
+ return { value, oldValue, action };
209
+ }
210
+ /**
211
+ * Update field value programmatically (internal method)
212
+ * Subclasses should provide type-safe public wrappers (e.g., change() method)
213
+ *
214
+ * @param value New value
215
+ * @param options.silent If true, won't emit change event (default: true)
216
+ * @param options.action Action type for the event (default: 'change')
217
+ */
218
+ setValue(value, options) {
219
+ const oldValue = this.getValue();
220
+ this.value = value;
221
+ this.writeValue(value);
222
+ if ((options == null ? void 0 : options.silent) === false) {
223
+ const payload = this.getEventPayload(value, oldValue, options.action || "change");
224
+ this.emit("change", { detail: payload });
225
+ }
226
+ }
227
+ /**
228
+ * Reset field to specified value or default value
229
+ *
230
+ * @param value Value to reset to, defaults to defaultValue prop
231
+ * @param options.silent If false, will emit reset event (default: true)
232
+ */
233
+ reset(value, options) {
234
+ const resetValue = value !== void 0 ? value : this.defaultValue;
235
+ this.setValue(resetValue, { ...options, action: "reset" });
236
+ }
237
+ /**
238
+ * Clear the field value
239
+ *
240
+ * @param options.silent If false, will emit clear event (default: true)
241
+ */
242
+ clear(options) {
243
+ this.setValue("", { ...options, action: "clear" });
244
+ }
245
+ /**
246
+ * Handle clear button click
247
+ * Clears the field and dispatches event
248
+ */
249
+ onClear() {
250
+ this.clear({ silent: false });
251
+ }
252
+ /**
253
+ * Handle reset button click
254
+ * Resets to default value and dispatches event
255
+ */
256
+ onReset() {
257
+ this.reset(void 0, { silent: false });
258
+ }
259
+ };
260
+ /**
261
+ * Define base field properties (extends AeicoElement properties)
262
+ */
263
+ __publicField(_AeicoField, "props", {
264
+ value: { type: String },
265
+ defaultValue: { type: String },
266
+ resettable: { type: Boolean },
267
+ resetText: { type: String },
268
+ resetTitle: { type: String },
269
+ clearable: { type: Boolean },
270
+ clearText: { type: String },
271
+ clearTitle: { type: String },
272
+ actionButtonStyle: { type: String },
273
+ size: { type: String },
274
+ disabled: { type: Boolean },
275
+ label: { type: String },
276
+ labelPlacement: { type: String },
277
+ required: { type: Boolean },
278
+ helperText: { type: String },
279
+ error: { type: String }
280
+ });
281
+ /**
282
+ * Property watchers
283
+ */
284
+ __publicField(_AeicoField, "watchers", {
285
+ disabled: "onDisabledChanged",
286
+ error: "onErrorChanged"
287
+ });
288
+ __publicField(_AeicoField, "_fieldIdCounter", 0);
289
+ let AeicoField = _AeicoField;
290
+ const fieldLabelCSS = ':host {\n --field-label-gap: 4px;\n --field-label-col-gap: 8px;\n --field-label-width: 100px;\n --field-label-font-size: 0.875em;\n --field-label-color: inherit;\n --field-required-color: var(--red, #dc3545);\n --field-helper-color: var(--color-text-muted, #6e6e6e);\n --field-error-color: var(--red, #dc3545);\n}\n\n:host([label]) {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--field-label-gap);\n}\n\n:host([label][label-placement="left"]) {\n display: grid;\n grid-template-columns: var(--field-label-width) 1fr;\n column-gap: var(--field-label-col-gap);\n row-gap: var(--field-label-gap);\n align-items: start;\n}\n\n:host([label][label-placement="left"]) .field-label {\n align-self: center;\n}\n\n:host([label][label-placement="left"]) .field-helper,\n:host([label][label-placement="left"]) .field-error {\n grid-column: 2;\n}\n\n.field-label {\n font-size: var(--field-label-font-size);\n color: var(--field-label-color);\n user-select: none;\n line-height: 1.4;\n}\n\n.field-required {\n color: var(--field-required-color);\n margin-left: 2px;\n}\n\n.field-helper {\n font-size: 0.8em;\n color: var(--field-helper-color);\n line-height: 1.4;\n}\n\n.field-error {\n font-size: 0.8em;\n color: var(--field-error-color);\n line-height: 1.4;\n}\n\n/* Action controls container (integrated style) */\n.action-controls {\n display: flex;\n flex-direction: row;\n align-items: stretch;\n margin-left: calc(-1 * var(--field-action-gap, 4px) - 1px);\n border: var(--field-action-border-width, 1px) solid var(--field-action-border-color, var(--border-subtle));\n border-radius: 0 var(--field-action-border-radius, 2px) var(--field-action-border-radius, 2px) 0;\n overflow: hidden;\n flex-shrink: 0;\n transition: border-color 0.12s;\n background: var(--field-action-bg, var(--surface-base));\n position: relative;\n z-index: 1;\n align-self: stretch;\n}\n\n.action-controls .action-btn {\n border: none;\n background: transparent;\n color: var(--field-action-color, var(--color-text-muted));\n font-size: 0.875em;\n line-height: 1;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 0.5em;\n transition: background 0.12s;\n}\n\n.action-controls .action-btn:hover:not(:disabled) {\n background: var(--field-action-bg-hover, var(--surface-raised));\n}\n\n.action-controls .action-btn:active:not(:disabled) {\n background: var(--field-action-bg-focus, var(--surface-raised));\n}\n\n.action-controls .action-btn:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.action-controls .action-btn + .action-btn {\n border-left: var(--field-action-border-width, 1px) solid var(--field-action-border-color, var(--border-subtle));\n}\n\n.input-container:has(input:focus) ~ .action-controls,\n.input-container:has(input:focus) .action-controls,\n.container:has(.trigger.open) ~ .action-controls,\n.container:has(.trigger.open) .action-controls {\n border-color: var(--field-action-border-color-focus, var(--border-focus));\n}\n\n.input-container:has(input:hover:not(:focus)) ~ .action-controls,\n.input-container:has(input:hover:not(:focus)) .action-controls,\n.container:has(.trigger:hover:not(.disabled)) ~ .action-controls,\n.container:has(.trigger:hover:not(.disabled)) .action-controls {\n border-color: var(--field-action-border-color-hover, var(--border-default));\n}\n';
291
+ const actionButtonCSS = "/* Action button base styles — shared by clear-btn and reset-btn (standalone mode) */\n.clear-btn:not(.action-btn),\n.reset-btn:not(.action-btn) {\n width: 1.333em;\n height: 1.333em;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n line-height: 1;\n}\n\n.clear-btn:not(.action-btn) {\n border-radius: var(--clear-btn-border-radius);\n background: var(--clear-btn-bg);\n color: var(--clear-btn-color);\n transition: var(--clear-btn-transition);\n}\n\n.reset-btn:not(.action-btn) {\n border-radius: var(--reset-btn-border-radius);\n background: var(--reset-btn-bg);\n color: var(--reset-btn-color);\n transition: var(--reset-btn-transition);\n}\n\n.clear-btn:not(.action-btn):hover {\n background: var(--clear-btn-bg-hover);\n color: var(--clear-btn-color-hover);\n}\n\n.reset-btn:not(.action-btn):hover {\n background: var(--reset-btn-bg-hover);\n color: var(--reset-btn-color-hover);\n}\n";
292
+ export {
293
+ AeicoField as A,
294
+ actionButtonCSS as a,
295
+ fieldLabelCSS as f
296
+ };
297
+ //# sourceMappingURL=action-button.js.map