stimeo-ui 0.17.0 → 0.18.0

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 (297) hide show
  1. package/CHANGELOG.md +106 -1
  2. package/README.md +19 -10
  3. package/dist/cable/index.d.ts +9 -8
  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 +289 -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 +64 -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 +199 -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.js +52 -43
  97. package/dist/controllers/form_field_controller.js.map +1 -1
  98. package/dist/controllers/form_validation_controller.d.ts +3 -3
  99. package/dist/controllers/form_validation_controller.js +18 -11
  100. package/dist/controllers/form_validation_controller.js.map +1 -1
  101. package/dist/controllers/frame_loading_controller.d.ts +13 -12
  102. package/dist/controllers/frame_loading_controller.js +55 -48
  103. package/dist/controllers/frame_loading_controller.js.map +1 -1
  104. package/dist/controllers/highlight_controller.d.ts +5 -4
  105. package/dist/controllers/highlight_controller.js.map +1 -1
  106. package/dist/controllers/hover_card_controller.d.ts +4 -1
  107. package/dist/controllers/hover_card_controller.js +67 -61
  108. package/dist/controllers/hover_card_controller.js.map +1 -1
  109. package/dist/controllers/idle_controller.d.ts +6 -5
  110. package/dist/controllers/idle_controller.js +10 -6
  111. package/dist/controllers/idle_controller.js.map +1 -1
  112. package/dist/controllers/input_mask_controller.d.ts +30 -13
  113. package/dist/controllers/input_mask_controller.js +411 -24
  114. package/dist/controllers/input_mask_controller.js.map +1 -1
  115. package/dist/controllers/intersection_controller.js +3 -0
  116. package/dist/controllers/intersection_controller.js.map +1 -1
  117. package/dist/controllers/lazy_frame_controller.d.ts +3 -2
  118. package/dist/controllers/lazy_frame_controller.js +15 -3
  119. package/dist/controllers/lazy_frame_controller.js.map +1 -1
  120. package/dist/controllers/listbox_controller.d.ts +10 -7
  121. package/dist/controllers/listbox_controller.js +260 -79
  122. package/dist/controllers/listbox_controller.js.map +1 -1
  123. package/dist/controllers/local_time_controller.d.ts +8 -6
  124. package/dist/controllers/local_time_controller.js +48 -13
  125. package/dist/controllers/local_time_controller.js.map +1 -1
  126. package/dist/controllers/masonry_controller.js +11 -4
  127. package/dist/controllers/masonry_controller.js.map +1 -1
  128. package/dist/controllers/menu_controller.d.ts +24 -5
  129. package/dist/controllers/menu_controller.js +138 -82
  130. package/dist/controllers/menu_controller.js.map +1 -1
  131. package/dist/controllers/menubar_controller.d.ts +49 -7
  132. package/dist/controllers/menubar_controller.js +65 -19
  133. package/dist/controllers/menubar_controller.js.map +1 -1
  134. package/dist/controllers/meter_controller.d.ts +13 -20
  135. package/dist/controllers/meter_controller.js +270 -24
  136. package/dist/controllers/meter_controller.js.map +1 -1
  137. package/dist/controllers/multi_select_controller.d.ts +17 -15
  138. package/dist/controllers/multi_select_controller.js +251 -94
  139. package/dist/controllers/multi_select_controller.js.map +1 -1
  140. package/dist/controllers/navigation_menu_controller.d.ts +19 -5
  141. package/dist/controllers/navigation_menu_controller.js +67 -19
  142. package/dist/controllers/navigation_menu_controller.js.map +1 -1
  143. package/dist/controllers/nested_form_controller.js +98 -64
  144. package/dist/controllers/nested_form_controller.js.map +1 -1
  145. package/dist/controllers/network_status_controller.js +70 -52
  146. package/dist/controllers/network_status_controller.js.map +1 -1
  147. package/dist/controllers/number_input_controller.d.ts +24 -6
  148. package/dist/controllers/number_input_controller.js +344 -94
  149. package/dist/controllers/number_input_controller.js.map +1 -1
  150. package/dist/controllers/optimistic_controller.d.ts +8 -5
  151. package/dist/controllers/optimistic_controller.js +29 -11
  152. package/dist/controllers/optimistic_controller.js.map +1 -1
  153. package/dist/controllers/otp_controller.d.ts +35 -4
  154. package/dist/controllers/otp_controller.js +502 -104
  155. package/dist/controllers/otp_controller.js.map +1 -1
  156. package/dist/controllers/overflow_indicator_controller.js +6 -0
  157. package/dist/controllers/overflow_indicator_controller.js.map +1 -1
  158. package/dist/controllers/overflow_menu_controller.d.ts +10 -9
  159. package/dist/controllers/overflow_menu_controller.js +136 -21
  160. package/dist/controllers/overflow_menu_controller.js.map +1 -1
  161. package/dist/controllers/pagination_controller.d.ts +3 -2
  162. package/dist/controllers/pagination_controller.js +47 -14
  163. package/dist/controllers/pagination_controller.js.map +1 -1
  164. package/dist/controllers/password_reveal_controller.d.ts +5 -4
  165. package/dist/controllers/password_reveal_controller.js +52 -49
  166. package/dist/controllers/password_reveal_controller.js.map +1 -1
  167. package/dist/controllers/password_strength_controller.d.ts +1 -1
  168. package/dist/controllers/password_strength_controller.js +13 -6
  169. package/dist/controllers/password_strength_controller.js.map +1 -1
  170. package/dist/controllers/persist_controller.js +48 -128
  171. package/dist/controllers/persist_controller.js.map +1 -1
  172. package/dist/controllers/pointer_drag_controller.d.ts +19 -8
  173. package/dist/controllers/pointer_drag_controller.js +249 -23
  174. package/dist/controllers/pointer_drag_controller.js.map +1 -1
  175. package/dist/controllers/popover_controller.d.ts +3 -3
  176. package/dist/controllers/popover_controller.js +82 -65
  177. package/dist/controllers/popover_controller.js.map +1 -1
  178. package/dist/controllers/portal_controller.js +6 -0
  179. package/dist/controllers/portal_controller.js.map +1 -1
  180. package/dist/controllers/preview_guard_controller.js +14 -3
  181. package/dist/controllers/preview_guard_controller.js.map +1 -1
  182. package/dist/controllers/progress_controller.d.ts +9 -19
  183. package/dist/controllers/progress_controller.js +271 -27
  184. package/dist/controllers/progress_controller.js.map +1 -1
  185. package/dist/controllers/radio_group_controller.d.ts +11 -8
  186. package/dist/controllers/radio_group_controller.js +167 -80
  187. package/dist/controllers/radio_group_controller.js.map +1 -1
  188. package/dist/controllers/range_slider_controller.d.ts +4 -3
  189. package/dist/controllers/range_slider_controller.js +27 -7
  190. package/dist/controllers/range_slider_controller.js.map +1 -1
  191. package/dist/controllers/rating_controller.js +93 -57
  192. package/dist/controllers/rating_controller.js.map +1 -1
  193. package/dist/controllers/read_more_controller.js +10 -6
  194. package/dist/controllers/read_more_controller.js.map +1 -1
  195. package/dist/controllers/reading_progress_controller.js +22 -5
  196. package/dist/controllers/reading_progress_controller.js.map +1 -1
  197. package/dist/controllers/relative_time_controller.d.ts +4 -4
  198. package/dist/controllers/relative_time_controller.js +75 -11
  199. package/dist/controllers/relative_time_controller.js.map +1 -1
  200. package/dist/controllers/reset_on_restore_controller.d.ts +3 -3
  201. package/dist/controllers/reset_on_restore_controller.js +6 -0
  202. package/dist/controllers/reset_on_restore_controller.js.map +1 -1
  203. package/dist/controllers/resizable_controller.d.ts +3 -0
  204. package/dist/controllers/resizable_controller.js +55 -22
  205. package/dist/controllers/resizable_controller.js.map +1 -1
  206. package/dist/controllers/roving_controller.d.ts +3 -3
  207. package/dist/controllers/roving_controller.js +10 -4
  208. package/dist/controllers/roving_controller.js.map +1 -1
  209. package/dist/controllers/scroll_area_controller.js +129 -88
  210. package/dist/controllers/scroll_area_controller.js.map +1 -1
  211. package/dist/controllers/scroll_restore_controller.d.ts +3 -3
  212. package/dist/controllers/scroll_restore_controller.js +14 -2
  213. package/dist/controllers/scroll_restore_controller.js.map +1 -1
  214. package/dist/controllers/scroll_visibility_controller.js +93 -60
  215. package/dist/controllers/scroll_visibility_controller.js.map +1 -1
  216. package/dist/controllers/scrollspy_controller.js +11 -5
  217. package/dist/controllers/scrollspy_controller.js.map +1 -1
  218. package/dist/controllers/separator_controller.d.ts +1 -1
  219. package/dist/controllers/separator_controller.js +59 -43
  220. package/dist/controllers/separator_controller.js.map +1 -1
  221. package/dist/controllers/sidebar_controller.d.ts +1 -1
  222. package/dist/controllers/sidebar_controller.js +150 -122
  223. package/dist/controllers/sidebar_controller.js.map +1 -1
  224. package/dist/controllers/skeleton_controller.js +55 -48
  225. package/dist/controllers/skeleton_controller.js.map +1 -1
  226. package/dist/controllers/slider_controller.d.ts +2 -1
  227. package/dist/controllers/slider_controller.js +27 -6
  228. package/dist/controllers/slider_controller.js.map +1 -1
  229. package/dist/controllers/smart_sticky_header_controller.d.ts +1 -1
  230. package/dist/controllers/smart_sticky_header_controller.js +13 -5
  231. package/dist/controllers/smart_sticky_header_controller.js.map +1 -1
  232. package/dist/controllers/sortable_controller.d.ts +4 -4
  233. package/dist/controllers/sortable_controller.js +27 -14
  234. package/dist/controllers/sortable_controller.js.map +1 -1
  235. package/dist/controllers/spinner_controller.js +55 -48
  236. package/dist/controllers/spinner_controller.js.map +1 -1
  237. package/dist/controllers/step_indicator_controller.d.ts +4 -4
  238. package/dist/controllers/step_indicator_controller.js +6 -0
  239. package/dist/controllers/step_indicator_controller.js.map +1 -1
  240. package/dist/controllers/stepper_controller.d.ts +2 -3
  241. package/dist/controllers/stepper_controller.js +6 -0
  242. package/dist/controllers/stepper_controller.js.map +1 -1
  243. package/dist/controllers/stick_to_bottom_controller.d.ts +3 -1
  244. package/dist/controllers/stick_to_bottom_controller.js +19 -8
  245. package/dist/controllers/stick_to_bottom_controller.js.map +1 -1
  246. package/dist/controllers/sticky_observer_controller.js +49 -43
  247. package/dist/controllers/sticky_observer_controller.js.map +1 -1
  248. package/dist/controllers/submit_once_controller.d.ts +2 -1
  249. package/dist/controllers/submit_once_controller.js +145 -85
  250. package/dist/controllers/submit_once_controller.js.map +1 -1
  251. package/dist/controllers/switch_controller.d.ts +7 -4
  252. package/dist/controllers/switch_controller.js +172 -28
  253. package/dist/controllers/switch_controller.js.map +1 -1
  254. package/dist/controllers/tabs_controller.d.ts +7 -4
  255. package/dist/controllers/tabs_controller.js +6 -1
  256. package/dist/controllers/tabs_controller.js.map +1 -1
  257. package/dist/controllers/tags_input_controller.d.ts +4 -3
  258. package/dist/controllers/tags_input_controller.js +157 -28
  259. package/dist/controllers/tags_input_controller.js.map +1 -1
  260. package/dist/controllers/textarea_autosize_controller.d.ts +1 -1
  261. package/dist/controllers/textarea_autosize_controller.js +40 -19
  262. package/dist/controllers/textarea_autosize_controller.js.map +1 -1
  263. package/dist/controllers/theme_controller.d.ts +3 -2
  264. package/dist/controllers/theme_controller.js +10 -4
  265. package/dist/controllers/theme_controller.js.map +1 -1
  266. package/dist/controllers/time_picker_controller.d.ts +38 -5
  267. package/dist/controllers/time_picker_controller.js +192 -54
  268. package/dist/controllers/time_picker_controller.js.map +1 -1
  269. package/dist/controllers/toast_controller.d.ts +4 -5
  270. package/dist/controllers/toast_controller.js +58 -27
  271. package/dist/controllers/toast_controller.js.map +1 -1
  272. package/dist/controllers/toggle_group_controller.d.ts +2 -3
  273. package/dist/controllers/toggle_group_controller.js +158 -56
  274. package/dist/controllers/toggle_group_controller.js.map +1 -1
  275. package/dist/controllers/toolbar_controller.d.ts +8 -6
  276. package/dist/controllers/toolbar_controller.js +150 -21
  277. package/dist/controllers/toolbar_controller.js.map +1 -1
  278. package/dist/controllers/tooltip_controller.d.ts +4 -1
  279. package/dist/controllers/tooltip_controller.js.map +1 -1
  280. package/dist/controllers/transition_controller.js.map +1 -1
  281. package/dist/controllers/tree_view_controller.d.ts +1 -1
  282. package/dist/controllers/tree_view_controller.js +134 -25
  283. package/dist/controllers/tree_view_controller.js.map +1 -1
  284. package/dist/index.d.ts +2 -0
  285. package/dist/index.js +2451 -1312
  286. package/dist/index.js.map +1 -1
  287. package/dist/inspector/cli.d.ts +15 -11
  288. package/dist/inspector/cli.js +16 -3
  289. package/dist/inspector/cli.js.map +1 -1
  290. package/dist/inspector/cli_bin.js +53 -8
  291. package/dist/inspector/cli_bin.js.map +1 -1
  292. package/dist/inspector/examples.json +13 -13
  293. package/dist/inspector/manifest.json +19 -5
  294. package/dist/positioning/index.d.ts +7 -7
  295. package/dist/positioning/index.js +6 -0
  296. package/dist/positioning/index.js.map +1 -1
  297. package/package.json +10 -9
@@ -26,17 +26,32 @@ function isReservedArrowChord(event, allow = []) {
26
26
  if (!event.key.startsWith("Arrow")) return false;
27
27
  return event.altKey && !allow.includes("alt") || event.ctrlKey && !allow.includes("ctrl") || event.metaKey && !allow.includes("meta") || event.shiftKey && !allow.includes("shift");
28
28
  }
29
+ function hasModifierChord(event) {
30
+ return event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
31
+ }
32
+
33
+ function setAttributeIfChanged(element, name, value, beforeWrite) {
34
+ if (element.getAttribute(name) === value) return false;
35
+ beforeWrite?.();
36
+ if (value === null) element.removeAttribute(name);
37
+ else element.setAttribute(name, value);
38
+ return true;
39
+ }
29
40
 
30
41
  function sharedRegistry(key, create) {
31
42
  const symbol = Symbol.for(key);
32
43
  const scope = globalThis;
33
44
  const existing = scope[symbol];
34
45
  if (existing !== void 0) return existing;
35
- const registry = create();
36
- Object.defineProperty(globalThis, symbol, { value: registry });
37
- return registry;
46
+ const registry2 = create();
47
+ Object.defineProperty(globalThis, symbol, { value: registry2 });
48
+ return registry2;
38
49
  }
39
50
 
51
+ var registry = sharedRegistry(
52
+ "stimeo-ui.attribute-lease.registry.v1",
53
+ () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
54
+ );
40
55
  function isAttributeValue(value) {
41
56
  return value === null || typeof value === "string";
42
57
  }
@@ -53,24 +68,46 @@ function readLeaseRecord(element, record) {
53
68
  return void 0;
54
69
  }
55
70
  }
56
- var AttributeLease = class _AttributeLease {
57
- static #registry = sharedRegistry(
58
- "stimeo-ui.attribute-lease.registry.v1",
59
- () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
60
- );
71
+ function attributeStack(element, attribute) {
72
+ const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
73
+ registry.stacks.set(element, byAttribute);
74
+ const known = byAttribute.get(attribute);
75
+ if (known) return known;
76
+ const found = [];
77
+ for (const record of registry.names.get(attribute) ?? []) {
78
+ const read = readLeaseRecord(element, record);
79
+ if (read) found.push({ ...read, record });
80
+ }
81
+ const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
82
+ const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
83
+ lease: null,
84
+ record,
85
+ written,
86
+ original,
87
+ linked: linked && index > 0
88
+ }));
89
+ byAttribute.set(attribute, stack);
90
+ return stack;
91
+ }
92
+ function findHold(stack, lease, record) {
93
+ return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
94
+ }
95
+ var AttributeLease = class {
61
96
  #attribute;
62
97
  #record;
63
98
  #base;
99
+ #preserveAuthor;
64
100
  #held = /* @__PURE__ */ new Set();
65
101
  constructor(attribute, owner, options = {}) {
66
102
  this.#attribute = attribute;
67
103
  this.#record = `data-${owner}-${attribute}-lease`;
68
104
  this.#base = options.base === true;
69
- const names = _AttributeLease.#registry.names;
105
+ this.#preserveAuthor = options.preserveAuthor === true;
106
+ const names = registry.names;
70
107
  names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
71
108
  }
72
109
  write(element, value) {
73
- const stack = this.#stack(element);
110
+ const stack = attributeStack(element, this.#attribute);
74
111
  const hold = this.#take(stack) ?? this.#acquire(element, stack);
75
112
  this.#held.add(element);
76
113
  const shows = !this.#covered(element, stack, hold);
@@ -80,8 +117,8 @@ var AttributeLease = class _AttributeLease {
80
117
  }
81
118
  return(element) {
82
119
  const held = this.#held.delete(element);
83
- const known = _AttributeLease.#registry.stacks.get(element)?.has(this.#attribute);
84
- const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
120
+ const known = registry.stacks.get(element)?.has(this.#attribute);
121
+ const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
85
122
  const hold = this.#take(stack);
86
123
  if (!hold) return false;
87
124
  const carries = element.getAttribute(this.#attribute) === hold.written;
@@ -99,31 +136,8 @@ var AttributeLease = class _AttributeLease {
99
136
  returnAll() {
100
137
  for (const element of Array.from(this.#held)) this.return(element);
101
138
  }
102
- #stack(element) {
103
- const stacks = _AttributeLease.#registry.stacks;
104
- const byAttribute = stacks.get(element) ?? /* @__PURE__ */ new Map();
105
- stacks.set(element, byAttribute);
106
- const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);
107
- byAttribute.set(this.#attribute, stack);
108
- return stack;
109
- }
110
- #seed(element) {
111
- const found = [];
112
- for (const record of _AttributeLease.#registry.names.get(this.#attribute) ?? []) {
113
- const read = readLeaseRecord(element, record);
114
- if (read) found.push({ ...read, record });
115
- }
116
- const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
117
- return found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
118
- lease: null,
119
- record,
120
- written,
121
- original,
122
- linked: linked && index > 0
123
- }));
124
- }
125
139
  #take(stack) {
126
- const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
140
+ const hold = findHold(stack, this, this.#record);
127
141
  if (hold) hold.lease = this;
128
142
  return hold;
129
143
  }
@@ -132,7 +146,7 @@ var AttributeLease = class _AttributeLease {
132
146
  const top = stack.at(-1);
133
147
  const bottom = stack[0];
134
148
  const over = top?.written === current ? top : void 0;
135
- const from = this.#base ? bottom : over;
149
+ const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
136
150
  const hold = {
137
151
  lease: this,
138
152
  record: this.#record,
@@ -162,15 +176,101 @@ var AttributeLease = class _AttributeLease {
162
176
  );
163
177
  });
164
178
  for (const [name, recorded] of records) {
165
- if (element.getAttribute(name) === recorded) continue;
166
- if (recorded === null) element.removeAttribute(name);
167
- else element.setAttribute(name, recorded);
179
+ setAttributeIfChanged(element, name, recorded);
168
180
  }
169
181
  }
170
182
  #reflect(element, value) {
171
- if (element.getAttribute(this.#attribute) === value) return;
172
- if (value === null) element.removeAttribute(this.#attribute);
173
- else element.setAttribute(this.#attribute, value);
183
+ setAttributeIfChanged(element, this.#attribute, value);
184
+ }
185
+ };
186
+
187
+ var AuthoredMutationWatcher = class {
188
+ #onAuthored;
189
+ #claims = null;
190
+ #observer = null;
191
+ constructor(onAuthored) {
192
+ this.#onAuthored = onAuthored;
193
+ }
194
+ observe(root, options) {
195
+ this.disconnect();
196
+ const observer = new MutationObserver((records) => {
197
+ if (this.#observer !== observer) return;
198
+ const authored = this.#filter(records);
199
+ if (authored.length > 0) this.#onAuthored(authored);
200
+ });
201
+ this.#observer = observer;
202
+ this.#claims = { attributes: /* @__PURE__ */ new Map(), children: /* @__PURE__ */ new Map() };
203
+ observer.observe(root, {
204
+ attributes: true,
205
+ attributeFilter: [...options.attributes],
206
+ subtree: options.subtree ?? false,
207
+ childList: options.childList ?? false
208
+ });
209
+ if (options.ancestorAttributes) {
210
+ let ancestor = root.parentElement;
211
+ while (ancestor) {
212
+ observer.observe(ancestor, {
213
+ attributes: true,
214
+ attributeFilter: [...options.ancestorAttributes]
215
+ });
216
+ ancestor = ancestor.parentElement;
217
+ }
218
+ }
219
+ }
220
+ claim(target, name, value) {
221
+ const claims = this.#claims?.attributes;
222
+ let attributes = claims?.get(target);
223
+ if (!attributes) {
224
+ attributes = /* @__PURE__ */ new Map();
225
+ claims?.set(target, attributes);
226
+ }
227
+ const pending = attributes.get(name);
228
+ attributes.set(name, { value, count: (pending?.count ?? 0) + 1 });
229
+ }
230
+ claimCurrent(target, name) {
231
+ this.claim(target, name, target.getAttribute(name));
232
+ }
233
+ claimChildList(target, added, removed) {
234
+ const claims = this.#claims?.children;
235
+ const pending = claims?.get(target) ?? { added: /* @__PURE__ */ new Map(), removed: /* @__PURE__ */ new Map() };
236
+ for (const node of added) pending.added.set(node, (pending.added.get(node) ?? 0) + 1);
237
+ for (const node of removed) pending.removed.set(node, (pending.removed.get(node) ?? 0) + 1);
238
+ claims?.set(target, pending);
239
+ }
240
+ take() {
241
+ return this.#filter(this.#observer?.takeRecords() ?? []);
242
+ }
243
+ disconnect() {
244
+ this.#observer?.disconnect();
245
+ this.#observer = null;
246
+ this.#claims = null;
247
+ }
248
+ #filter(records) {
249
+ const authored = records.filter((record) => !this.#consume(record));
250
+ this.#claims?.attributes.clear();
251
+ this.#claims?.children.clear();
252
+ return authored;
253
+ }
254
+ #consume(record) {
255
+ if (record.type === "attributes") {
256
+ const target = record.target;
257
+ const pending2 = this.#claims?.attributes.get(target)?.get(record.attributeName);
258
+ if (!pending2 || pending2.count === 0 || target.getAttribute(record.attributeName) !== pending2.value) {
259
+ return false;
260
+ }
261
+ pending2.count -= 1;
262
+ return true;
263
+ }
264
+ const pending = this.#claims?.children.get(record.target);
265
+ if (!pending) return false;
266
+ const added = [...record.addedNodes];
267
+ const removed = [...record.removedNodes];
268
+ if (added.some((node) => !pending.added.get(node)) || removed.some((node) => !pending.removed.get(node))) {
269
+ return false;
270
+ }
271
+ for (const node of added) pending.added.set(node, (pending.added.get(node) ?? 0) - 1);
272
+ for (const node of removed) pending.removed.set(node, (pending.removed.get(node) ?? 0) - 1);
273
+ return true;
174
274
  }
175
275
  };
176
276
 
@@ -210,6 +310,9 @@ var MicrotaskCoalescer = class {
210
310
  this.#queued = false;
211
311
  this.#generation += 1;
212
312
  }
313
+ get pending() {
314
+ return this.#queued;
315
+ }
213
316
  schedule() {
214
317
  if (!this.#active || this.#queued) return;
215
318
  this.#queued = true;
@@ -240,6 +343,9 @@ var MorphRenderWatcher = class {
240
343
  schedule() {
241
344
  this.#pass.schedule();
242
345
  }
346
+ get pending() {
347
+ return this.#pass.pending;
348
+ }
243
349
  disconnect() {
244
350
  this.#listeners.dispose();
245
351
  this.#pass.cancel();
@@ -269,6 +375,87 @@ function scrollOptionIntoView(list, option) {
269
375
  }
270
376
  }
271
377
 
378
+ var OwnedText = class {
379
+ #attribute;
380
+ #channel;
381
+ #guard;
382
+ #writes = /* @__PURE__ */ new WeakMap();
383
+ constructor(attribute, channel = "text", guard = () => true) {
384
+ this.#attribute = attribute;
385
+ this.#channel = channel;
386
+ this.#guard = guard;
387
+ }
388
+ hasRecord(element) {
389
+ return element.hasAttribute(this.#attribute);
390
+ }
391
+ read(element, evidence = {}) {
392
+ if (evidence.source === "live") return this.#writes.get(element) ?? null;
393
+ const raw = element.getAttribute(this.#attribute);
394
+ if (raw === null) return null;
395
+ try {
396
+ const record = JSON.parse(raw);
397
+ if (!Array.isArray(record) || record.length !== 3 || record[0] !== this.#channel || typeof record[1] !== "string" || typeof record[2] !== "string")
398
+ return null;
399
+ return { original: record[1], written: record[2] };
400
+ } catch {
401
+ return null;
402
+ }
403
+ }
404
+ owns(element, evidence = {}) {
405
+ return this.#ownedRecord(element, evidence) !== null;
406
+ }
407
+ #ownedRecord(element, evidence) {
408
+ const record = this.read(element, evidence);
409
+ if (record === null || !this.#guard(element)) return null;
410
+ if (this.#channel === "text" && element.firstElementChild !== null) return null;
411
+ const current = this.#current(element);
412
+ return current === record.written || evidence.source === "live" && evidence.allowOriginal === true && current === record.original ? record : null;
413
+ }
414
+ write(element, written, original, force = false) {
415
+ const current = this.#current(element);
416
+ if (current === null) return;
417
+ const before = original ?? this.#writes.get(element)?.original ?? this.read(element)?.original ?? current;
418
+ if (force || current !== written) this.#put(element, written);
419
+ this.remember(element, written, before);
420
+ }
421
+ remember(element, written, original) {
422
+ const current = this.#current(element);
423
+ if (current === null) return;
424
+ const before = original ?? this.#writes.get(element)?.original ?? this.read(element)?.original ?? current;
425
+ this.#writes.set(element, { original: before, written });
426
+ setAttributeIfChanged(
427
+ element,
428
+ this.#attribute,
429
+ JSON.stringify([this.#channel, before, written])
430
+ );
431
+ }
432
+ clear(element, evidence = {}) {
433
+ if (!this.owns(element, evidence)) return false;
434
+ if (this.#current(element) !== "") this.#put(element, "");
435
+ this.forget(element);
436
+ return true;
437
+ }
438
+ restore(element, evidence = {}) {
439
+ const record = this.#ownedRecord(element, evidence);
440
+ if (record === null) return false;
441
+ if (this.#current(element) !== record.original) this.#put(element, record.original);
442
+ this.forget(element);
443
+ return true;
444
+ }
445
+ forget(element) {
446
+ setAttributeIfChanged(element, this.#attribute, null);
447
+ this.#writes.delete(element);
448
+ }
449
+ #current(element) {
450
+ if (this.#channel === "text") return element.textContent ?? "";
451
+ return element instanceof HTMLInputElement ? element.value : null;
452
+ }
453
+ #put(element, text) {
454
+ if (this.#channel === "text") element.textContent = text;
455
+ else if (element instanceof HTMLInputElement) element.value = text;
456
+ }
457
+ };
458
+
272
459
  function targetSelector(identifier, name) {
273
460
  return `[data-${identifier}-target~="${name}"]`;
274
461
  }
@@ -354,11 +541,10 @@ function findTypeaheadMatch(items, from, query, label = (item) => typeaheadLabel
354
541
  }
355
542
 
356
543
  var OBSERVED_ATTRIBUTES = ["aria-selected", "data-value"];
357
- function setAttributeIfChanged(element, name, value) {
358
- if (element.getAttribute(name) !== value) element.setAttribute(name, value);
359
- }
360
544
  var ListboxController = class extends Controller {
545
+ #labelText = new OwnedText(`data-${this.identifier}-owns-label`);
361
546
  #moves = new MoveCounter();
547
+ #connectionGeneration = 0;
362
548
  static targets = ["trigger", "value", "list", "option", "field"];
363
549
  static values = {
364
550
  placeholder: { type: String, default: "" }
@@ -368,7 +554,9 @@ var ListboxController = class extends Controller {
368
554
  #activeId = null;
369
555
  #activeOrder = [];
370
556
  #reconcile = new MorphRenderWatcher(() => this.#reconcileOptions());
371
- #observer = null;
557
+ #observer = new AuthoredMutationWatcher((records) => {
558
+ if (this.#concernsOptions(records)) this.#reconcile.schedule();
559
+ });
372
560
  #settled = { option: null, value: "" };
373
561
  #shownList = null;
374
562
  #listHidden = new AttributeLease("hidden", this.identifier);
@@ -378,10 +566,11 @@ var ListboxController = class extends Controller {
378
566
  this.identifier
379
567
  );
380
568
  #typeahead = new Typeahead();
569
+ #listeners = new ListenerSet();
381
570
  connect() {
382
571
  this.#normalizeSelection();
383
572
  this.close();
384
- document.addEventListener("click", this.#onOutsideClick, true);
573
+ this.#listeners.add(document, "click", this.#onOutsideClick, { capture: true });
385
574
  this.#settled = this.#selection();
386
575
  this.#reconcile.observe(this.element);
387
576
  this.#observeOptions();
@@ -470,10 +659,10 @@ var ListboxController = class extends Controller {
470
659
  return { option, value: option ? this.#optionValue(option) : "" };
471
660
  }
472
661
  disconnect() {
662
+ this.#connectionGeneration += 1;
473
663
  this.#reconcile.disconnect();
474
- this.#observer?.disconnect();
475
- this.#observer = null;
476
- document.removeEventListener("click", this.#onOutsideClick, true);
664
+ this.#observer.disconnect();
665
+ this.#listeners.dispose();
477
666
  this.#typeahead.reset();
478
667
  }
479
668
  toggle(event) {
@@ -487,6 +676,7 @@ var ListboxController = class extends Controller {
487
676
  onTriggerKeydown(event) {
488
677
  if (event.defaultPrevented) return;
489
678
  if (isReservedArrowChord(event)) return;
679
+ if ((event.key === "Home" || event.key === "End") && hasModifierChord(event)) return;
490
680
  if (!this.#isClosed) this.#reconcileActive();
491
681
  const options = this.optionTargets;
492
682
  const length = options.length;
@@ -589,21 +779,22 @@ var ListboxController = class extends Controller {
589
779
  this.triggerTarget.focus();
590
780
  }
591
781
  #selectOption(option, reason = "user") {
782
+ const generation = this.#connectionGeneration;
592
783
  const { value, fieldChanged } = this.#applySelection(option);
593
784
  const changed = option !== this.#settled.option || value !== this.#settled.value;
594
785
  this.#settled = { option, value };
595
786
  if (!changed) return true;
596
787
  const token = this.#moves.record();
597
788
  if (fieldChanged) commitField(this.fieldTarget);
598
- if (!this.#moves.isLatest(token)) return false;
789
+ if (generation !== this.#connectionGeneration || !this.#moves.isLatest(token)) return false;
599
790
  this.dispatch("change", { detail: { value, option, reason } });
600
791
  return this.#moves.isLatest(token);
601
792
  }
602
793
  #applySelection(option) {
603
794
  for (const candidate of this.optionTargets) {
604
- setAttributeIfChanged(candidate, "aria-selected", candidate === option ? "true" : "false");
795
+ this.#writeSelection(candidate, candidate === option ? "true" : "false");
605
796
  }
606
- this.#dropOwnRecords();
797
+ this.#flushMutations();
607
798
  const value = option ? this.#optionValue(option) : "";
608
799
  this.#renderLabel(option);
609
800
  const fieldChanged = this.hasFieldTarget && writeField(this.fieldTarget, value);
@@ -612,26 +803,16 @@ var ListboxController = class extends Controller {
612
803
  #renderLabel(option) {
613
804
  if (!this.hasValueTarget) return;
614
805
  const label = this.valueTarget;
615
- const ownsLabel = `data-${this.identifier}-owns-label`;
616
- const originalLabel = `data-${this.identifier}-original-label`;
617
- const owned = label.getAttribute(ownsLabel) === label.textContent && label.childElementCount === 0;
618
- if (option === void 0 && !owned && label.hasAttribute(ownsLabel)) return;
806
+ const owned = this.#labelText.owns(label);
807
+ if (option === void 0 && !owned && this.#labelText.hasRecord(label)) return;
619
808
  const text = option ? this.#optionLabel(option) : this.placeholderValue || null;
620
809
  if (text === null) {
621
- if (!owned) return;
622
- label.textContent = label.getAttribute(originalLabel) ?? "";
623
- label.removeAttribute(ownsLabel);
624
- label.removeAttribute(originalLabel);
810
+ this.#labelText.restore(label);
625
811
  return;
626
812
  }
627
- if (!owned) {
628
- const current = (label.textContent ?? "").trim();
629
- if (option === void 0 || current !== text) {
630
- setAttributeIfChanged(label, originalLabel, current);
631
- }
632
- }
633
- if (label.textContent !== text) label.textContent = text;
634
- setAttributeIfChanged(label, ownsLabel, text);
813
+ const current = (label.textContent ?? "").trim();
814
+ const original = owned ? void 0 : option === void 0 || current !== text ? current : this.#labelText.read(label)?.original ?? "";
815
+ this.#labelText.write(label, text, original);
635
816
  }
636
817
  #optionLabel(option) {
637
818
  return (option.textContent ?? "").trim();
@@ -640,22 +821,17 @@ var ListboxController = class extends Controller {
640
821
  return option.dataset.value ?? this.#optionLabel(option);
641
822
  }
642
823
  #observeOptions() {
643
- const observer = new MutationObserver((records) => {
644
- if (this.#concernsOptions(records)) this.#reconcile.schedule();
645
- });
646
- observer.observe(this.element, {
824
+ this.#observer.observe(this.element, {
647
825
  subtree: true,
648
- attributes: true,
649
- attributeFilter: OBSERVED_ATTRIBUTES
826
+ attributes: OBSERVED_ATTRIBUTES
650
827
  });
651
- this.#observer = observer;
652
828
  }
653
829
  #concernsOptions(records) {
654
830
  const options = new Set(this.optionTargets);
655
831
  return records.some((record) => options.has(record.target));
656
832
  }
657
- #dropOwnRecords() {
658
- this.#observer?.takeRecords();
833
+ #flushMutations() {
834
+ if (this.#concernsOptions(this.#observer.take())) this.#reconcile.schedule();
659
835
  }
660
836
  #setActive(index) {
661
837
  const options = this.optionTargets;
@@ -728,6 +904,11 @@ var ListboxController = class extends Controller {
728
904
  get #isClosed() {
729
905
  return !this.hasListTarget || this.listTarget.hidden !== false;
730
906
  }
907
+ #writeSelection(target, value) {
908
+ setAttributeIfChanged(target, "aria-selected", value, () => {
909
+ this.#observer.claim(target, "aria-selected", value);
910
+ });
911
+ }
731
912
  };
732
913
 
733
914
  export { ListboxController };