stimeo-ui 0.17.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/CHANGELOG.md +136 -2
  2. package/README.md +19 -10
  3. package/dist/cable/index.d.ts +11 -9
  4. package/dist/cable/index.js +22 -14
  5. package/dist/cable/index.js.map +1 -1
  6. package/dist/coerce-JtZVNG5h.d.ts +20 -0
  7. package/dist/controllers/accordion_controller.js +14 -6
  8. package/dist/controllers/accordion_controller.js.map +1 -1
  9. package/dist/controllers/alert_dialog_controller.js +145 -118
  10. package/dist/controllers/alert_dialog_controller.js.map +1 -1
  11. package/dist/controllers/announcer_controller.d.ts +5 -3
  12. package/dist/controllers/announcer_controller.js +113 -17
  13. package/dist/controllers/announcer_controller.js.map +1 -1
  14. package/dist/controllers/auto_submit_controller.js +185 -60
  15. package/dist/controllers/auto_submit_controller.js.map +1 -1
  16. package/dist/controllers/avatar_controller.js +55 -43
  17. package/dist/controllers/avatar_controller.js.map +1 -1
  18. package/dist/controllers/breadcrumb_controller.js.map +1 -1
  19. package/dist/controllers/bulk_select_controller.d.ts +3 -3
  20. package/dist/controllers/bulk_select_controller.js +64 -50
  21. package/dist/controllers/bulk_select_controller.js.map +1 -1
  22. package/dist/controllers/calendar_controller.d.ts +15 -12
  23. package/dist/controllers/calendar_controller.js +55 -53
  24. package/dist/controllers/calendar_controller.js.map +1 -1
  25. package/dist/controllers/carousel_controller.d.ts +9 -5
  26. package/dist/controllers/carousel_controller.js +124 -86
  27. package/dist/controllers/carousel_controller.js.map +1 -1
  28. package/dist/controllers/character_counter_controller.d.ts +27 -6
  29. package/dist/controllers/character_counter_controller.js +291 -95
  30. package/dist/controllers/character_counter_controller.js.map +1 -1
  31. package/dist/controllers/checkbox_controller.js +6 -0
  32. package/dist/controllers/checkbox_controller.js.map +1 -1
  33. package/dist/controllers/clipboard_controller.js +118 -27
  34. package/dist/controllers/clipboard_controller.js.map +1 -1
  35. package/dist/controllers/collapsible_controller.d.ts +1 -1
  36. package/dist/controllers/collapsible_controller.js +52 -49
  37. package/dist/controllers/collapsible_controller.js.map +1 -1
  38. package/dist/controllers/color_picker_controller.js +29 -7
  39. package/dist/controllers/color_picker_controller.js.map +1 -1
  40. package/dist/controllers/combobox_controller.d.ts +1 -1
  41. package/dist/controllers/combobox_controller.js +210 -71
  42. package/dist/controllers/combobox_controller.js.map +1 -1
  43. package/dist/controllers/command_palette_controller.d.ts +9 -9
  44. package/dist/controllers/command_palette_controller.js +290 -140
  45. package/dist/controllers/command_palette_controller.js.map +1 -1
  46. package/dist/controllers/conditional_fields_controller.js +145 -58
  47. package/dist/controllers/conditional_fields_controller.js.map +1 -1
  48. package/dist/controllers/confirm_controller.js +145 -118
  49. package/dist/controllers/confirm_controller.js.map +1 -1
  50. package/dist/controllers/context_menu_controller.d.ts +49 -14
  51. package/dist/controllers/context_menu_controller.js +138 -73
  52. package/dist/controllers/context_menu_controller.js.map +1 -1
  53. package/dist/controllers/count_up_controller.js.map +1 -1
  54. package/dist/controllers/countdown_controller.d.ts +2 -2
  55. package/dist/controllers/countdown_controller.js +109 -21
  56. package/dist/controllers/countdown_controller.js.map +1 -1
  57. package/dist/controllers/currency_input_controller.d.ts +75 -11
  58. package/dist/controllers/currency_input_controller.js +446 -72
  59. package/dist/controllers/currency_input_controller.js.map +1 -1
  60. package/dist/controllers/data_grid_controller.d.ts +10 -8
  61. package/dist/controllers/data_grid_controller.js +134 -28
  62. package/dist/controllers/data_grid_controller.js.map +1 -1
  63. package/dist/controllers/date_range_picker_controller.d.ts +12 -9
  64. package/dist/controllers/date_range_picker_controller.js +93 -72
  65. package/dist/controllers/date_range_picker_controller.js.map +1 -1
  66. package/dist/controllers/dialog_controller.d.ts +4 -5
  67. package/dist/controllers/dialog_controller.js +145 -118
  68. package/dist/controllers/dialog_controller.js.map +1 -1
  69. package/dist/controllers/direct_upload_controller.d.ts +1 -1
  70. package/dist/controllers/direct_upload_controller.js +24 -14
  71. package/dist/controllers/direct_upload_controller.js.map +1 -1
  72. package/dist/controllers/dirty_form_controller.d.ts +6 -1
  73. package/dist/controllers/dirty_form_controller.js +68 -31
  74. package/dist/controllers/dirty_form_controller.js.map +1 -1
  75. package/dist/controllers/dismissible_controller.js +66 -46
  76. package/dist/controllers/dismissible_controller.js.map +1 -1
  77. package/dist/controllers/drawer_controller.js +145 -118
  78. package/dist/controllers/drawer_controller.js.map +1 -1
  79. package/dist/controllers/dropdown_controller.js +76 -63
  80. package/dist/controllers/dropdown_controller.js.map +1 -1
  81. package/dist/controllers/editable_controller.js +200 -62
  82. package/dist/controllers/editable_controller.js.map +1 -1
  83. package/dist/controllers/empty_state_controller.js +13 -6
  84. package/dist/controllers/empty_state_controller.js.map +1 -1
  85. package/dist/controllers/file_dropzone_controller.d.ts +3 -0
  86. package/dist/controllers/file_dropzone_controller.js +55 -48
  87. package/dist/controllers/file_dropzone_controller.js.map +1 -1
  88. package/dist/controllers/filter_controller.js +9 -2
  89. package/dist/controllers/filter_controller.js.map +1 -1
  90. package/dist/controllers/flash_controller.d.ts +4 -4
  91. package/dist/controllers/flash_controller.js +66 -33
  92. package/dist/controllers/flash_controller.js.map +1 -1
  93. package/dist/controllers/focus_controller.d.ts +3 -3
  94. package/dist/controllers/focus_controller.js +39 -14
  95. package/dist/controllers/focus_controller.js.map +1 -1
  96. package/dist/controllers/form_field_controller.d.ts +2 -1
  97. package/dist/controllers/form_field_controller.js +52 -43
  98. package/dist/controllers/form_field_controller.js.map +1 -1
  99. package/dist/controllers/form_validation_controller.d.ts +3 -3
  100. package/dist/controllers/form_validation_controller.js +18 -11
  101. package/dist/controllers/form_validation_controller.js.map +1 -1
  102. package/dist/controllers/frame_loading_controller.d.ts +13 -12
  103. package/dist/controllers/frame_loading_controller.js +55 -48
  104. package/dist/controllers/frame_loading_controller.js.map +1 -1
  105. package/dist/controllers/highlight_controller.d.ts +5 -4
  106. package/dist/controllers/highlight_controller.js.map +1 -1
  107. package/dist/controllers/hover_card_controller.d.ts +4 -1
  108. package/dist/controllers/hover_card_controller.js +67 -61
  109. package/dist/controllers/hover_card_controller.js.map +1 -1
  110. package/dist/controllers/idle_controller.d.ts +6 -5
  111. package/dist/controllers/idle_controller.js +10 -6
  112. package/dist/controllers/idle_controller.js.map +1 -1
  113. package/dist/controllers/input_mask_controller.d.ts +31 -13
  114. package/dist/controllers/input_mask_controller.js +434 -24
  115. package/dist/controllers/input_mask_controller.js.map +1 -1
  116. package/dist/controllers/intersection_controller.js +3 -0
  117. package/dist/controllers/intersection_controller.js.map +1 -1
  118. package/dist/controllers/lazy_frame_controller.d.ts +3 -2
  119. package/dist/controllers/lazy_frame_controller.js +15 -3
  120. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  121. package/dist/controllers/listbox_controller.d.ts +10 -7
  122. package/dist/controllers/listbox_controller.js +260 -79
  123. package/dist/controllers/listbox_controller.js.map +1 -1
  124. package/dist/controllers/local_time_controller.d.ts +8 -6
  125. package/dist/controllers/local_time_controller.js +48 -13
  126. package/dist/controllers/local_time_controller.js.map +1 -1
  127. package/dist/controllers/masonry_controller.js +11 -4
  128. package/dist/controllers/masonry_controller.js.map +1 -1
  129. package/dist/controllers/menu_controller.d.ts +24 -5
  130. package/dist/controllers/menu_controller.js +138 -82
  131. package/dist/controllers/menu_controller.js.map +1 -1
  132. package/dist/controllers/menubar_controller.d.ts +49 -7
  133. package/dist/controllers/menubar_controller.js +65 -19
  134. package/dist/controllers/menubar_controller.js.map +1 -1
  135. package/dist/controllers/meter_controller.d.ts +13 -20
  136. package/dist/controllers/meter_controller.js +270 -24
  137. package/dist/controllers/meter_controller.js.map +1 -1
  138. package/dist/controllers/multi_select_controller.d.ts +19 -16
  139. package/dist/controllers/multi_select_controller.js +272 -95
  140. package/dist/controllers/multi_select_controller.js.map +1 -1
  141. package/dist/controllers/navigation_menu_controller.d.ts +19 -5
  142. package/dist/controllers/navigation_menu_controller.js +67 -19
  143. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  144. package/dist/controllers/nested_form_controller.js +98 -64
  145. package/dist/controllers/nested_form_controller.js.map +1 -1
  146. package/dist/controllers/network_status_controller.js +70 -52
  147. package/dist/controllers/network_status_controller.js.map +1 -1
  148. package/dist/controllers/number_input_controller.d.ts +24 -6
  149. package/dist/controllers/number_input_controller.js +344 -94
  150. package/dist/controllers/number_input_controller.js.map +1 -1
  151. package/dist/controllers/optimistic_controller.d.ts +8 -5
  152. package/dist/controllers/optimistic_controller.js +29 -11
  153. package/dist/controllers/optimistic_controller.js.map +1 -1
  154. package/dist/controllers/otp_controller.d.ts +35 -4
  155. package/dist/controllers/otp_controller.js +502 -104
  156. package/dist/controllers/otp_controller.js.map +1 -1
  157. package/dist/controllers/overflow_indicator_controller.js +6 -0
  158. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  159. package/dist/controllers/overflow_menu_controller.d.ts +10 -9
  160. package/dist/controllers/overflow_menu_controller.js +136 -21
  161. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  162. package/dist/controllers/pagination_controller.d.ts +3 -2
  163. package/dist/controllers/pagination_controller.js +47 -14
  164. package/dist/controllers/pagination_controller.js.map +1 -1
  165. package/dist/controllers/password_reveal_controller.d.ts +5 -4
  166. package/dist/controllers/password_reveal_controller.js +52 -49
  167. package/dist/controllers/password_reveal_controller.js.map +1 -1
  168. package/dist/controllers/password_strength_controller.d.ts +1 -1
  169. package/dist/controllers/password_strength_controller.js +13 -6
  170. package/dist/controllers/password_strength_controller.js.map +1 -1
  171. package/dist/controllers/persist_controller.js +48 -128
  172. package/dist/controllers/persist_controller.js.map +1 -1
  173. package/dist/controllers/pointer_drag_controller.d.ts +20 -8
  174. package/dist/controllers/pointer_drag_controller.js +255 -24
  175. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  176. package/dist/controllers/popover_controller.d.ts +9 -5
  177. package/dist/controllers/popover_controller.js +91 -65
  178. package/dist/controllers/popover_controller.js.map +1 -1
  179. package/dist/controllers/portal_controller.js +6 -0
  180. package/dist/controllers/portal_controller.js.map +1 -1
  181. package/dist/controllers/preview_guard_controller.js +14 -3
  182. package/dist/controllers/preview_guard_controller.js.map +1 -1
  183. package/dist/controllers/progress_controller.d.ts +9 -19
  184. package/dist/controllers/progress_controller.js +271 -27
  185. package/dist/controllers/progress_controller.js.map +1 -1
  186. package/dist/controllers/radio_group_controller.d.ts +11 -8
  187. package/dist/controllers/radio_group_controller.js +167 -80
  188. package/dist/controllers/radio_group_controller.js.map +1 -1
  189. package/dist/controllers/range_slider_controller.d.ts +4 -3
  190. package/dist/controllers/range_slider_controller.js +27 -7
  191. package/dist/controllers/range_slider_controller.js.map +1 -1
  192. package/dist/controllers/rating_controller.js +93 -57
  193. package/dist/controllers/rating_controller.js.map +1 -1
  194. package/dist/controllers/read_more_controller.js +10 -6
  195. package/dist/controllers/read_more_controller.js.map +1 -1
  196. package/dist/controllers/reading_progress_controller.js +22 -5
  197. package/dist/controllers/reading_progress_controller.js.map +1 -1
  198. package/dist/controllers/relative_time_controller.d.ts +4 -4
  199. package/dist/controllers/relative_time_controller.js +75 -11
  200. package/dist/controllers/relative_time_controller.js.map +1 -1
  201. package/dist/controllers/reset_on_restore_controller.d.ts +3 -3
  202. package/dist/controllers/reset_on_restore_controller.js +6 -0
  203. package/dist/controllers/reset_on_restore_controller.js.map +1 -1
  204. package/dist/controllers/resizable_controller.d.ts +3 -0
  205. package/dist/controllers/resizable_controller.js +55 -22
  206. package/dist/controllers/resizable_controller.js.map +1 -1
  207. package/dist/controllers/roving_controller.d.ts +3 -3
  208. package/dist/controllers/roving_controller.js +10 -4
  209. package/dist/controllers/roving_controller.js.map +1 -1
  210. package/dist/controllers/scroll_area_controller.js +129 -88
  211. package/dist/controllers/scroll_area_controller.js.map +1 -1
  212. package/dist/controllers/scroll_restore_controller.d.ts +3 -3
  213. package/dist/controllers/scroll_restore_controller.js +14 -2
  214. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  215. package/dist/controllers/scroll_visibility_controller.js +93 -60
  216. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  217. package/dist/controllers/scrollspy_controller.js +11 -5
  218. package/dist/controllers/scrollspy_controller.js.map +1 -1
  219. package/dist/controllers/separator_controller.d.ts +1 -1
  220. package/dist/controllers/separator_controller.js +59 -43
  221. package/dist/controllers/separator_controller.js.map +1 -1
  222. package/dist/controllers/sidebar_controller.d.ts +1 -1
  223. package/dist/controllers/sidebar_controller.js +150 -122
  224. package/dist/controllers/sidebar_controller.js.map +1 -1
  225. package/dist/controllers/skeleton_controller.js +55 -48
  226. package/dist/controllers/skeleton_controller.js.map +1 -1
  227. package/dist/controllers/slider_controller.d.ts +2 -1
  228. package/dist/controllers/slider_controller.js +27 -6
  229. package/dist/controllers/slider_controller.js.map +1 -1
  230. package/dist/controllers/smart_sticky_header_controller.d.ts +1 -1
  231. package/dist/controllers/smart_sticky_header_controller.js +13 -5
  232. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  233. package/dist/controllers/sortable_controller.d.ts +4 -4
  234. package/dist/controllers/sortable_controller.js +27 -14
  235. package/dist/controllers/sortable_controller.js.map +1 -1
  236. package/dist/controllers/spinner_controller.js +55 -48
  237. package/dist/controllers/spinner_controller.js.map +1 -1
  238. package/dist/controllers/step_indicator_controller.d.ts +4 -4
  239. package/dist/controllers/step_indicator_controller.js +6 -0
  240. package/dist/controllers/step_indicator_controller.js.map +1 -1
  241. package/dist/controllers/stepper_controller.d.ts +2 -3
  242. package/dist/controllers/stepper_controller.js +6 -0
  243. package/dist/controllers/stepper_controller.js.map +1 -1
  244. package/dist/controllers/stick_to_bottom_controller.d.ts +3 -1
  245. package/dist/controllers/stick_to_bottom_controller.js +19 -8
  246. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  247. package/dist/controllers/sticky_observer_controller.js +49 -43
  248. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  249. package/dist/controllers/submit_once_controller.d.ts +2 -1
  250. package/dist/controllers/submit_once_controller.js +145 -85
  251. package/dist/controllers/submit_once_controller.js.map +1 -1
  252. package/dist/controllers/switch_controller.d.ts +7 -4
  253. package/dist/controllers/switch_controller.js +172 -28
  254. package/dist/controllers/switch_controller.js.map +1 -1
  255. package/dist/controllers/tabs_controller.d.ts +7 -4
  256. package/dist/controllers/tabs_controller.js +6 -1
  257. package/dist/controllers/tabs_controller.js.map +1 -1
  258. package/dist/controllers/tags_input_controller.d.ts +4 -3
  259. package/dist/controllers/tags_input_controller.js +157 -28
  260. package/dist/controllers/tags_input_controller.js.map +1 -1
  261. package/dist/controllers/textarea_autosize_controller.d.ts +1 -1
  262. package/dist/controllers/textarea_autosize_controller.js +40 -19
  263. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  264. package/dist/controllers/theme_controller.d.ts +3 -2
  265. package/dist/controllers/theme_controller.js +10 -4
  266. package/dist/controllers/theme_controller.js.map +1 -1
  267. package/dist/controllers/time_picker_controller.d.ts +38 -5
  268. package/dist/controllers/time_picker_controller.js +192 -54
  269. package/dist/controllers/time_picker_controller.js.map +1 -1
  270. package/dist/controllers/toast_controller.d.ts +4 -5
  271. package/dist/controllers/toast_controller.js +58 -27
  272. package/dist/controllers/toast_controller.js.map +1 -1
  273. package/dist/controllers/toggle_group_controller.d.ts +2 -3
  274. package/dist/controllers/toggle_group_controller.js +158 -56
  275. package/dist/controllers/toggle_group_controller.js.map +1 -1
  276. package/dist/controllers/toolbar_controller.d.ts +8 -6
  277. package/dist/controllers/toolbar_controller.js +150 -21
  278. package/dist/controllers/toolbar_controller.js.map +1 -1
  279. package/dist/controllers/tooltip_controller.d.ts +4 -1
  280. package/dist/controllers/tooltip_controller.js.map +1 -1
  281. package/dist/controllers/transition_controller.js.map +1 -1
  282. package/dist/controllers/tree_view_controller.d.ts +1 -1
  283. package/dist/controllers/tree_view_controller.js +134 -25
  284. package/dist/controllers/tree_view_controller.js.map +1 -1
  285. package/dist/index.d.ts +4 -1
  286. package/dist/index.js +2515 -1315
  287. package/dist/index.js.map +1 -1
  288. package/dist/inspector/cli.d.ts +25 -12
  289. package/dist/inspector/cli.js +21 -3
  290. package/dist/inspector/cli.js.map +1 -1
  291. package/dist/inspector/cli_bin.d.ts +1 -1
  292. package/dist/inspector/cli_bin.js +62 -8
  293. package/dist/inspector/cli_bin.js.map +1 -1
  294. package/dist/inspector/examples.json +13 -13
  295. package/dist/inspector/manifest.json +19 -5
  296. package/dist/positioning/index.d.ts +9 -8
  297. package/dist/positioning/index.js +6 -0
  298. package/dist/positioning/index.js.map +1 -1
  299. package/package.json +11 -10
@@ -22,13 +22,18 @@ function actionSource(source) {
22
22
  };
23
23
  }
24
24
 
25
+ function setAttributeIfChanged(element, name, value, beforeWrite) {
26
+ if (element.getAttribute(name) === value) return false;
27
+ if (value === null) element.removeAttribute(name);
28
+ else element.setAttribute(name, value);
29
+ return true;
30
+ }
31
+
25
32
  function syncActiveOption(options, active) {
26
33
  let written = 0;
27
34
  for (const option of options) {
28
35
  const next = option === active ? "true" : "false";
29
- if (option.getAttribute("aria-selected") === next) continue;
30
- option.setAttribute("aria-selected", next);
31
- written += 1;
36
+ if (setAttributeIfChanged(option, "aria-selected", next)) written += 1;
32
37
  }
33
38
  return written;
34
39
  }
@@ -37,17 +42,24 @@ function isReservedArrowChord(event, allow = []) {
37
42
  if (!event.key.startsWith("Arrow")) return false;
38
43
  return event.altKey && !allow.includes("alt") || event.ctrlKey && !allow.includes("ctrl") || event.metaKey && !allow.includes("meta") || event.shiftKey && !allow.includes("shift");
39
44
  }
45
+ function hasModifierChord(event) {
46
+ return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
47
+ }
40
48
 
41
49
  function sharedRegistry(key, create) {
42
50
  const symbol = Symbol.for(key);
43
51
  const scope = globalThis;
44
52
  const existing = scope[symbol];
45
53
  if (existing !== void 0) return existing;
46
- const registry = create();
47
- Object.defineProperty(globalThis, symbol, { value: registry });
48
- return registry;
54
+ const registry2 = create();
55
+ Object.defineProperty(globalThis, symbol, { value: registry2 });
56
+ return registry2;
49
57
  }
50
58
 
59
+ var registry = sharedRegistry(
60
+ "stimeo-ui.attribute-lease.registry.v1",
61
+ () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
62
+ );
51
63
  function isAttributeValue(value) {
52
64
  return value === null || typeof value === "string";
53
65
  }
@@ -64,24 +76,46 @@ function readLeaseRecord(element, record) {
64
76
  return void 0;
65
77
  }
66
78
  }
67
- var AttributeLease = class _AttributeLease {
68
- static #registry = sharedRegistry(
69
- "stimeo-ui.attribute-lease.registry.v1",
70
- () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
71
- );
79
+ function attributeStack(element, attribute) {
80
+ const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
81
+ registry.stacks.set(element, byAttribute);
82
+ const known = byAttribute.get(attribute);
83
+ if (known) return known;
84
+ const found = [];
85
+ for (const record of registry.names.get(attribute) ?? []) {
86
+ const read = readLeaseRecord(element, record);
87
+ if (read) found.push({ ...read, record });
88
+ }
89
+ const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
90
+ const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
91
+ lease: null,
92
+ record,
93
+ written,
94
+ original,
95
+ linked: linked && index > 0
96
+ }));
97
+ byAttribute.set(attribute, stack);
98
+ return stack;
99
+ }
100
+ function findHold(stack, lease, record) {
101
+ return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
102
+ }
103
+ var AttributeLease = class {
72
104
  #attribute;
73
105
  #record;
74
106
  #base;
107
+ #preserveAuthor;
75
108
  #held = /* @__PURE__ */ new Set();
76
109
  constructor(attribute, owner, options = {}) {
77
110
  this.#attribute = attribute;
78
111
  this.#record = `data-${owner}-${attribute}-lease`;
79
112
  this.#base = options.base === true;
80
- const names = _AttributeLease.#registry.names;
113
+ this.#preserveAuthor = options.preserveAuthor === true;
114
+ const names = registry.names;
81
115
  names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
82
116
  }
83
117
  write(element, value) {
84
- const stack = this.#stack(element);
118
+ const stack = attributeStack(element, this.#attribute);
85
119
  const hold = this.#take(stack) ?? this.#acquire(element, stack);
86
120
  this.#held.add(element);
87
121
  const shows = !this.#covered(element, stack, hold);
@@ -91,8 +125,8 @@ var AttributeLease = class _AttributeLease {
91
125
  }
92
126
  return(element) {
93
127
  const held = this.#held.delete(element);
94
- const known = _AttributeLease.#registry.stacks.get(element)?.has(this.#attribute);
95
- const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
128
+ const known = registry.stacks.get(element)?.has(this.#attribute);
129
+ const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
96
130
  const hold = this.#take(stack);
97
131
  if (!hold) return false;
98
132
  const carries = element.getAttribute(this.#attribute) === hold.written;
@@ -110,31 +144,8 @@ var AttributeLease = class _AttributeLease {
110
144
  returnAll() {
111
145
  for (const element of Array.from(this.#held)) this.return(element);
112
146
  }
113
- #stack(element) {
114
- const stacks = _AttributeLease.#registry.stacks;
115
- const byAttribute = stacks.get(element) ?? /* @__PURE__ */ new Map();
116
- stacks.set(element, byAttribute);
117
- const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);
118
- byAttribute.set(this.#attribute, stack);
119
- return stack;
120
- }
121
- #seed(element) {
122
- const found = [];
123
- for (const record of _AttributeLease.#registry.names.get(this.#attribute) ?? []) {
124
- const read = readLeaseRecord(element, record);
125
- if (read) found.push({ ...read, record });
126
- }
127
- const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
128
- return found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
129
- lease: null,
130
- record,
131
- written,
132
- original,
133
- linked: linked && index > 0
134
- }));
135
- }
136
147
  #take(stack) {
137
- const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
148
+ const hold = findHold(stack, this, this.#record);
138
149
  if (hold) hold.lease = this;
139
150
  return hold;
140
151
  }
@@ -143,7 +154,7 @@ var AttributeLease = class _AttributeLease {
143
154
  const top = stack.at(-1);
144
155
  const bottom = stack[0];
145
156
  const over = top?.written === current ? top : void 0;
146
- const from = this.#base ? bottom : over;
157
+ const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
147
158
  const hold = {
148
159
  lease: this,
149
160
  record: this.#record,
@@ -173,15 +184,11 @@ var AttributeLease = class _AttributeLease {
173
184
  );
174
185
  });
175
186
  for (const [name, recorded] of records) {
176
- if (element.getAttribute(name) === recorded) continue;
177
- if (recorded === null) element.removeAttribute(name);
178
- else element.setAttribute(name, recorded);
187
+ setAttributeIfChanged(element, name, recorded);
179
188
  }
180
189
  }
181
190
  #reflect(element, value) {
182
- if (element.getAttribute(this.#attribute) === value) return;
183
- if (value === null) element.removeAttribute(this.#attribute);
184
- else element.setAttribute(this.#attribute, value);
191
+ setAttributeIfChanged(element, this.#attribute, value);
185
192
  }
186
193
  };
187
194
 
@@ -191,63 +198,182 @@ var COMPOSITION_INPUT_TYPES = /* @__PURE__ */ new Set([
191
198
  "deleteCompositionText",
192
199
  "deleteByComposition"
193
200
  ]);
201
+ function isCompositionInputType(inputType) {
202
+ return inputType !== void 0 && COMPOSITION_INPUT_TYPES.has(inputType);
203
+ }
204
+ var BEFORE_MORPH_ATTRIBUTE = "turbo:before-morph-attribute";
205
+ var textOf = (element) => element.value;
206
+ var holdsFocus = (element) => element instanceof Node && element.getRootNode().activeElement === element;
194
207
  var CompositionTracker = class {
195
208
  #observedTargets = /* @__PURE__ */ new Set();
196
- #activeTargets = /* @__PURE__ */ new Set();
209
+ #composition = null;
197
210
  #onStart;
198
211
  #onEnd;
212
+ #onAbandon;
199
213
  #confirmedTarget = null;
214
+ #keyComposing = false;
215
+ #connected = false;
216
+ #abandoned = null;
200
217
  constructor(options = {}) {
201
218
  this.#onStart = options.onStart;
202
219
  this.#onEnd = options.onEnd;
220
+ this.#onAbandon = options.onAbandon;
203
221
  }
204
222
  observe(target) {
223
+ this.#connected = true;
205
224
  if (this.#observedTargets.has(target)) return;
206
225
  target.addEventListener("compositionstart", this.#handleStart);
207
226
  target.addEventListener("compositionend", this.#handleEnd);
208
- target.addEventListener("keydown", this.#handleKeydown);
227
+ target.addEventListener("keydown", this.#handleKeydown, true);
228
+ target.addEventListener("beforeinput", this.#handleBeforeInput, true);
229
+ target.addEventListener("input", this.#handleInput, true);
230
+ target.addEventListener("blur", this.#handleBlur, true);
231
+ target.addEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
209
232
  this.#observedTargets.add(target);
210
233
  }
211
234
  unobserve(target) {
212
235
  if (!this.#observedTargets.delete(target)) return;
213
- target.removeEventListener("compositionstart", this.#handleStart);
214
- target.removeEventListener("compositionend", this.#handleEnd);
215
- target.removeEventListener("keydown", this.#handleKeydown);
216
- this.#activeTargets.delete(target);
236
+ this.#release(target);
237
+ if (this.#composition?.target === target) this.#letGo();
217
238
  if (this.#confirmedTarget === target) this.#confirmedTarget = null;
218
239
  }
219
240
  disconnect() {
220
- for (const target of this.#observedTargets) {
221
- target.removeEventListener("compositionstart", this.#handleStart);
222
- target.removeEventListener("compositionend", this.#handleEnd);
223
- target.removeEventListener("keydown", this.#handleKeydown);
224
- }
241
+ this.#connected = false;
242
+ for (const target of this.#observedTargets) this.#release(target);
225
243
  this.#observedTargets.clear();
226
- this.#activeTargets.clear();
244
+ this.#letGo();
227
245
  this.#confirmedTarget = null;
246
+ this.#keyComposing = false;
247
+ this.#abandoned = null;
228
248
  }
229
249
  isComposing(event) {
230
- return this.#activeTargets.size > 0 || event?.isComposing === true;
250
+ this.#settle();
251
+ return event?.isComposing === true || this.#composition !== null;
252
+ }
253
+ composingElement() {
254
+ this.#settle();
255
+ return this.#composition?.element ?? null;
256
+ }
257
+ owns(event) {
258
+ const element = this.composingElement();
259
+ return event.isComposing === true || element !== null && element === event.target;
231
260
  }
232
261
  consumesConfirmedInput(event) {
233
262
  const confirmed = this.#confirmedTarget;
234
263
  this.#confirmedTarget = null;
235
264
  if (confirmed === null || confirmed !== event.target) return false;
236
265
  const inputType = event.inputType;
237
- return !inputType || COMPOSITION_INPUT_TYPES.has(inputType);
266
+ return !inputType || isCompositionInputType(inputType);
267
+ }
268
+ #release(target) {
269
+ target.removeEventListener("compositionstart", this.#handleStart);
270
+ target.removeEventListener("compositionend", this.#handleEnd);
271
+ target.removeEventListener("keydown", this.#handleKeydown, true);
272
+ target.removeEventListener("beforeinput", this.#handleBeforeInput, true);
273
+ target.removeEventListener("input", this.#handleInput, true);
274
+ target.removeEventListener("blur", this.#handleBlur, true);
275
+ target.removeEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
276
+ }
277
+ #letGo() {
278
+ const composition = this.#composition;
279
+ if (composition === null) return;
280
+ if (!holdsFocus(composition.element)) {
281
+ this.#composition = null;
282
+ return;
283
+ }
284
+ queueMicrotask(() => {
285
+ if (this.#composition !== composition || this.#observedTargets.has(composition.target)) {
286
+ return;
287
+ }
288
+ this.#composition = null;
289
+ if (!this.#connected) return;
290
+ this.#abandoned = { element: composition.element, inPlace: true };
291
+ this.#runAbandon();
292
+ });
293
+ }
294
+ #settle() {
295
+ const composition = this.#composition;
296
+ if (composition === null) return;
297
+ const { target, element, text } = composition;
298
+ if (target instanceof Node && element instanceof Node && !target.contains(element)) {
299
+ this.#composition = null;
300
+ } else if (textOf(element) !== text) {
301
+ this.#abandon(false);
302
+ }
303
+ }
304
+ #abandon(inPlace) {
305
+ this.#owe(inPlace);
306
+ this.#composition = null;
307
+ queueMicrotask(this.#runAbandon);
308
+ }
309
+ #owe(inPlace) {
310
+ const composition = this.#composition;
311
+ if (composition !== null) this.#abandoned = { element: composition.element, inPlace };
238
312
  }
313
+ #runAbandon = () => {
314
+ const abandoned = this.#abandoned;
315
+ if (abandoned === null) return;
316
+ this.#abandoned = null;
317
+ this.#onAbandon?.(abandoned.element, abandoned.inPlace);
318
+ };
239
319
  #handleStart = (event) => {
240
320
  this.#confirmedTarget = null;
241
- if (event.currentTarget) this.#activeTargets.add(event.currentTarget);
321
+ this.#settle();
322
+ this.#owe(true);
323
+ const target = event.currentTarget;
324
+ const element = event.target;
325
+ this.#composition = { target, element, text: textOf(element) };
326
+ this.#runAbandon();
242
327
  this.#onStart?.(event);
243
328
  };
244
329
  #handleEnd = (event) => {
245
- if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);
330
+ this.#runAbandon();
331
+ if (this.#composition?.target === event.currentTarget) this.#composition = null;
246
332
  this.#confirmedTarget = event.target;
247
333
  this.#onEnd?.(event);
248
334
  };
249
- #handleKeydown = () => {
335
+ #handleKeydown = (event) => {
336
+ this.#settle();
337
+ this.#runAbandon();
250
338
  this.#confirmedTarget = null;
339
+ this.#keyComposing = event.isComposing === true;
340
+ };
341
+ #handleBeforeInput = (event) => {
342
+ const keyComposing = this.#keyComposing;
343
+ this.#keyComposing = false;
344
+ this.#settle();
345
+ const { isComposing, inputType } = event;
346
+ if (this.#composition !== null && !keyComposing && !isComposing && inputType && !isCompositionInputType(inputType)) {
347
+ this.#abandon(true);
348
+ }
349
+ this.#runAbandon();
350
+ };
351
+ #handleInput = (event) => {
352
+ const composition = this.#composition;
353
+ const { isTrusted, isComposing, inputType } = event;
354
+ if (composition !== null && event.target === composition.element && (isTrusted || isComposing || isCompositionInputType(inputType))) {
355
+ composition.text = textOf(composition.element);
356
+ } else {
357
+ this.#settle();
358
+ }
359
+ this.#runAbandon();
360
+ };
361
+ #handleBlur = (event) => {
362
+ this.#settle();
363
+ this.#runAbandon();
364
+ const composition = this.#composition;
365
+ if (composition === null || composition.target === composition.element) return;
366
+ const { element } = composition;
367
+ if (!(element instanceof Node) || event.target !== element) return;
368
+ const root = element.getRootNode();
369
+ if (root.activeElement !== element) this.#composition = null;
370
+ };
371
+ #handleBeforeMorphAttribute = (event) => {
372
+ this.#settle();
373
+ const composition = this.#composition;
374
+ if (composition?.target !== event.currentTarget || event.target !== composition.element) return;
375
+ const detail = event.detail;
376
+ if (detail?.attributeName === "value") event.preventDefault();
251
377
  };
252
378
  };
253
379
 
@@ -255,6 +381,17 @@ function commitField(target) {
255
381
  target.dispatchEvent(new Event("change", { bubbles: true }));
256
382
  }
257
383
 
384
+ var ListenerSet = class {
385
+ #abort = new AbortController();
386
+ add(target, type, handler, options) {
387
+ target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
388
+ }
389
+ dispose() {
390
+ this.#abort.abort();
391
+ this.#abort = new AbortController();
392
+ }
393
+ };
394
+
258
395
  var MicrotaskCoalescer = class {
259
396
  #run;
260
397
  #queued = false;
@@ -271,6 +408,9 @@ var MicrotaskCoalescer = class {
271
408
  this.#queued = false;
272
409
  this.#generation += 1;
273
410
  }
411
+ get pending() {
412
+ return this.#queued;
413
+ }
274
414
  schedule() {
275
415
  if (!this.#active || this.#queued) return;
276
416
  this.#queued = true;
@@ -349,9 +489,8 @@ var StateRegions = class _StateRegions {
349
489
  const below = hold.linked ? stack[index - 1] : void 0;
350
490
  if (below) {
351
491
  if (region.hidden !== below.written) region.hidden = below.written;
352
- } else if (region.getAttribute("hidden") !== hold.authored) {
353
- if (hold.authored === null) region.removeAttribute("hidden");
354
- else region.setAttribute("hidden", hold.authored);
492
+ } else {
493
+ setAttributeIfChanged(region, "hidden", hold.authored);
355
494
  }
356
495
  }
357
496
  this.#mark(region, stack);
@@ -426,9 +565,7 @@ var StateRegions = class _StateRegions {
426
565
  );
427
566
  });
428
567
  for (const [name, recorded] of records) {
429
- if (region.getAttribute(name) === recorded) continue;
430
- if (recorded === null) region.removeAttribute(name);
431
- else region.setAttribute(name, recorded);
568
+ setAttributeIfChanged(region, name, recorded);
432
569
  }
433
570
  }
434
571
  #recorded(region, name) {
@@ -473,11 +610,12 @@ var ComboboxController = class extends Controller {
473
610
  #reconcile = new MicrotaskCoalescer(() => this.#reconcileOptions());
474
611
  #suppressOpen = false;
475
612
  #composition = new CompositionTracker({ onEnd: () => this.filter() });
613
+ #listeners = new ListenerSet();
476
614
  connect() {
477
615
  if (this.hasInputTarget) this.#composition.observe(this.inputTarget);
478
616
  this.close();
479
617
  this.#list = this.hasListTarget ? this.listTarget : null;
480
- document.addEventListener("click", this.#onOutsideClick, true);
618
+ this.#listeners.add(document, "click", this.#onOutsideClick, { capture: true });
481
619
  this.#connected = true;
482
620
  this.#reconcile.activate();
483
621
  }
@@ -485,7 +623,7 @@ var ComboboxController = class extends Controller {
485
623
  this.#connected = false;
486
624
  this.#reconcile.cancel();
487
625
  this.#composition.disconnect();
488
- document.removeEventListener("click", this.#onOutsideClick, true);
626
+ this.#listeners.dispose();
489
627
  }
490
628
  inputTargetConnected(input) {
491
629
  this.#composition.observe(input);
@@ -547,6 +685,7 @@ var ComboboxController = class extends Controller {
547
685
  if (this.#composition.isComposing(event)) return;
548
686
  if (event.defaultPrevented) return;
549
687
  if (isReservedArrowChord(event, ["alt"])) return;
688
+ if ((event.key === "Home" || event.key === "End") && hasModifierChord(event)) return;
550
689
  if (event.altKey && (event.key === "ArrowDown" || event.key === "ArrowUp")) {
551
690
  if (event.key === "ArrowDown" ? !this.#isClosed : this.#isClosed) return;
552
691
  event.preventDefault();