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
@@ -1,15 +1,26 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
3
+ function setAttributeIfChanged(element, name, value, beforeWrite) {
4
+ if (element.getAttribute(name) === value) return false;
5
+ if (value === null) element.removeAttribute(name);
6
+ else element.setAttribute(name, value);
7
+ return true;
8
+ }
9
+
3
10
  function sharedRegistry(key, create) {
4
11
  const symbol = Symbol.for(key);
5
12
  const scope = globalThis;
6
13
  const existing = scope[symbol];
7
14
  if (existing !== void 0) return existing;
8
- const registry = create();
9
- Object.defineProperty(globalThis, symbol, { value: registry });
10
- return registry;
15
+ const registry2 = create();
16
+ Object.defineProperty(globalThis, symbol, { value: registry2 });
17
+ return registry2;
11
18
  }
12
19
 
20
+ var registry = sharedRegistry(
21
+ "stimeo-ui.attribute-lease.registry.v1",
22
+ () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
23
+ );
13
24
  function isAttributeValue(value) {
14
25
  return value === null || typeof value === "string";
15
26
  }
@@ -26,24 +37,46 @@ function readLeaseRecord(element, record) {
26
37
  return void 0;
27
38
  }
28
39
  }
29
- var AttributeLease = class _AttributeLease {
30
- static #registry = sharedRegistry(
31
- "stimeo-ui.attribute-lease.registry.v1",
32
- () => ({ stacks: /* @__PURE__ */ new WeakMap(), names: /* @__PURE__ */ new Map() })
33
- );
40
+ function attributeStack(element, attribute) {
41
+ const byAttribute = registry.stacks.get(element) ?? /* @__PURE__ */ new Map();
42
+ registry.stacks.set(element, byAttribute);
43
+ const known = byAttribute.get(attribute);
44
+ if (known) return known;
45
+ const found = [];
46
+ for (const record of registry.names.get(attribute) ?? []) {
47
+ const read = readLeaseRecord(element, record);
48
+ if (read) found.push({ ...read, record });
49
+ }
50
+ const depth = ({ beneath }) => beneath.filter((name) => found.some((other) => other.record === name)).length;
51
+ const stack = found.sort((one, other) => depth(one) - depth(other)).map(({ record, written, original, linked }, index) => ({
52
+ lease: null,
53
+ record,
54
+ written,
55
+ original,
56
+ linked: linked && index > 0
57
+ }));
58
+ byAttribute.set(attribute, stack);
59
+ return stack;
60
+ }
61
+ function findHold(stack, lease, record) {
62
+ return stack.find((held) => held.lease === lease) ?? stack.find((held) => held.lease === null && held.record === record);
63
+ }
64
+ var AttributeLease = class {
34
65
  #attribute;
35
66
  #record;
36
67
  #base;
68
+ #preserveAuthor;
37
69
  #held = /* @__PURE__ */ new Set();
38
70
  constructor(attribute, owner, options = {}) {
39
71
  this.#attribute = attribute;
40
72
  this.#record = `data-${owner}-${attribute}-lease`;
41
73
  this.#base = options.base === true;
42
- const names = _AttributeLease.#registry.names;
74
+ this.#preserveAuthor = options.preserveAuthor === true;
75
+ const names = registry.names;
43
76
  names.set(attribute, (names.get(attribute) ?? /* @__PURE__ */ new Set()).add(this.#record));
44
77
  }
45
78
  write(element, value) {
46
- const stack = this.#stack(element);
79
+ const stack = attributeStack(element, this.#attribute);
47
80
  const hold = this.#take(stack) ?? this.#acquire(element, stack);
48
81
  this.#held.add(element);
49
82
  const shows = !this.#covered(element, stack, hold);
@@ -53,8 +86,8 @@ var AttributeLease = class _AttributeLease {
53
86
  }
54
87
  return(element) {
55
88
  const held = this.#held.delete(element);
56
- const known = _AttributeLease.#registry.stacks.get(element)?.has(this.#attribute);
57
- const stack = held || known || element.hasAttribute(this.#record) ? this.#stack(element) : [];
89
+ const known = registry.stacks.get(element)?.has(this.#attribute);
90
+ const stack = held || known || element.hasAttribute(this.#record) ? attributeStack(element, this.#attribute) : [];
58
91
  const hold = this.#take(stack);
59
92
  if (!hold) return false;
60
93
  const carries = element.getAttribute(this.#attribute) === hold.written;
@@ -72,31 +105,8 @@ var AttributeLease = class _AttributeLease {
72
105
  returnAll() {
73
106
  for (const element of Array.from(this.#held)) this.return(element);
74
107
  }
75
- #stack(element) {
76
- const stacks = _AttributeLease.#registry.stacks;
77
- const byAttribute = stacks.get(element) ?? /* @__PURE__ */ new Map();
78
- stacks.set(element, byAttribute);
79
- const stack = byAttribute.get(this.#attribute) ?? this.#seed(element);
80
- byAttribute.set(this.#attribute, stack);
81
- return stack;
82
- }
83
- #seed(element) {
84
- const found = [];
85
- for (const record of _AttributeLease.#registry.names.get(this.#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
- return 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
- }
98
108
  #take(stack) {
99
- const hold = stack.find((held) => held.lease === this) ?? stack.find((held) => held.lease === null && held.record === this.#record);
109
+ const hold = findHold(stack, this, this.#record);
100
110
  if (hold) hold.lease = this;
101
111
  return hold;
102
112
  }
@@ -105,7 +115,7 @@ var AttributeLease = class _AttributeLease {
105
115
  const top = stack.at(-1);
106
116
  const bottom = stack[0];
107
117
  const over = top?.written === current ? top : void 0;
108
- const from = this.#base ? bottom : over;
118
+ const from = this.#base ? this.#preserveAuthor && !stack.some((held) => held.written === current) ? void 0 : bottom : over;
109
119
  const hold = {
110
120
  lease: this,
111
121
  record: this.#record,
@@ -135,15 +145,11 @@ var AttributeLease = class _AttributeLease {
135
145
  );
136
146
  });
137
147
  for (const [name, recorded] of records) {
138
- if (element.getAttribute(name) === recorded) continue;
139
- if (recorded === null) element.removeAttribute(name);
140
- else element.setAttribute(name, recorded);
148
+ setAttributeIfChanged(element, name, recorded);
141
149
  }
142
150
  }
143
151
  #reflect(element, value) {
144
- if (element.getAttribute(this.#attribute) === value) return;
145
- if (value === null) element.removeAttribute(this.#attribute);
146
- else element.setAttribute(this.#attribute, value);
152
+ setAttributeIfChanged(element, this.#attribute, value);
147
153
  }
148
154
  };
149
155
 
@@ -153,66 +159,196 @@ var COMPOSITION_INPUT_TYPES = /* @__PURE__ */ new Set([
153
159
  "deleteCompositionText",
154
160
  "deleteByComposition"
155
161
  ]);
162
+ function isCompositionInputType(inputType) {
163
+ return inputType !== void 0 && COMPOSITION_INPUT_TYPES.has(inputType);
164
+ }
165
+ var BEFORE_MORPH_ATTRIBUTE = "turbo:before-morph-attribute";
166
+ var textOf = (element) => element.value;
167
+ var holdsFocus = (element) => element instanceof Node && element.getRootNode().activeElement === element;
156
168
  var CompositionTracker = class {
157
169
  #observedTargets = /* @__PURE__ */ new Set();
158
- #activeTargets = /* @__PURE__ */ new Set();
170
+ #composition = null;
159
171
  #onStart;
160
172
  #onEnd;
173
+ #onAbandon;
161
174
  #confirmedTarget = null;
175
+ #keyComposing = false;
176
+ #connected = false;
177
+ #abandoned = null;
162
178
  constructor(options = {}) {
163
179
  this.#onStart = options.onStart;
164
180
  this.#onEnd = options.onEnd;
181
+ this.#onAbandon = options.onAbandon;
165
182
  }
166
183
  observe(target) {
184
+ this.#connected = true;
167
185
  if (this.#observedTargets.has(target)) return;
168
186
  target.addEventListener("compositionstart", this.#handleStart);
169
187
  target.addEventListener("compositionend", this.#handleEnd);
170
- target.addEventListener("keydown", this.#handleKeydown);
188
+ target.addEventListener("keydown", this.#handleKeydown, true);
189
+ target.addEventListener("beforeinput", this.#handleBeforeInput, true);
190
+ target.addEventListener("input", this.#handleInput, true);
191
+ target.addEventListener("blur", this.#handleBlur, true);
192
+ target.addEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
171
193
  this.#observedTargets.add(target);
172
194
  }
173
195
  unobserve(target) {
174
196
  if (!this.#observedTargets.delete(target)) return;
175
- target.removeEventListener("compositionstart", this.#handleStart);
176
- target.removeEventListener("compositionend", this.#handleEnd);
177
- target.removeEventListener("keydown", this.#handleKeydown);
178
- this.#activeTargets.delete(target);
197
+ this.#release(target);
198
+ if (this.#composition?.target === target) this.#letGo();
179
199
  if (this.#confirmedTarget === target) this.#confirmedTarget = null;
180
200
  }
181
201
  disconnect() {
182
- for (const target of this.#observedTargets) {
183
- target.removeEventListener("compositionstart", this.#handleStart);
184
- target.removeEventListener("compositionend", this.#handleEnd);
185
- target.removeEventListener("keydown", this.#handleKeydown);
186
- }
202
+ this.#connected = false;
203
+ for (const target of this.#observedTargets) this.#release(target);
187
204
  this.#observedTargets.clear();
188
- this.#activeTargets.clear();
205
+ this.#letGo();
189
206
  this.#confirmedTarget = null;
207
+ this.#keyComposing = false;
208
+ this.#abandoned = null;
190
209
  }
191
210
  isComposing(event) {
192
- return this.#activeTargets.size > 0 || event?.isComposing === true;
211
+ this.#settle();
212
+ return event?.isComposing === true || this.#composition !== null;
213
+ }
214
+ composingElement() {
215
+ this.#settle();
216
+ return this.#composition?.element ?? null;
217
+ }
218
+ owns(event) {
219
+ const element = this.composingElement();
220
+ return event.isComposing === true || element !== null && element === event.target;
193
221
  }
194
222
  consumesConfirmedInput(event) {
195
223
  const confirmed = this.#confirmedTarget;
196
224
  this.#confirmedTarget = null;
197
225
  if (confirmed === null || confirmed !== event.target) return false;
198
226
  const inputType = event.inputType;
199
- return !inputType || COMPOSITION_INPUT_TYPES.has(inputType);
227
+ return !inputType || isCompositionInputType(inputType);
228
+ }
229
+ #release(target) {
230
+ target.removeEventListener("compositionstart", this.#handleStart);
231
+ target.removeEventListener("compositionend", this.#handleEnd);
232
+ target.removeEventListener("keydown", this.#handleKeydown, true);
233
+ target.removeEventListener("beforeinput", this.#handleBeforeInput, true);
234
+ target.removeEventListener("input", this.#handleInput, true);
235
+ target.removeEventListener("blur", this.#handleBlur, true);
236
+ target.removeEventListener(BEFORE_MORPH_ATTRIBUTE, this.#handleBeforeMorphAttribute);
237
+ }
238
+ #letGo() {
239
+ const composition = this.#composition;
240
+ if (composition === null) return;
241
+ if (!holdsFocus(composition.element)) {
242
+ this.#composition = null;
243
+ return;
244
+ }
245
+ queueMicrotask(() => {
246
+ if (this.#composition !== composition || this.#observedTargets.has(composition.target)) {
247
+ return;
248
+ }
249
+ this.#composition = null;
250
+ if (!this.#connected) return;
251
+ this.#abandoned = { element: composition.element, inPlace: true };
252
+ this.#runAbandon();
253
+ });
254
+ }
255
+ #settle() {
256
+ const composition = this.#composition;
257
+ if (composition === null) return;
258
+ const { target, element, text } = composition;
259
+ if (target instanceof Node && element instanceof Node && !target.contains(element)) {
260
+ this.#composition = null;
261
+ } else if (textOf(element) !== text) {
262
+ this.#abandon(false);
263
+ }
200
264
  }
265
+ #abandon(inPlace) {
266
+ this.#owe(inPlace);
267
+ this.#composition = null;
268
+ queueMicrotask(this.#runAbandon);
269
+ }
270
+ #owe(inPlace) {
271
+ const composition = this.#composition;
272
+ if (composition !== null) this.#abandoned = { element: composition.element, inPlace };
273
+ }
274
+ #runAbandon = () => {
275
+ const abandoned = this.#abandoned;
276
+ if (abandoned === null) return;
277
+ this.#abandoned = null;
278
+ this.#onAbandon?.(abandoned.element, abandoned.inPlace);
279
+ };
201
280
  #handleStart = (event) => {
202
281
  this.#confirmedTarget = null;
203
- if (event.currentTarget) this.#activeTargets.add(event.currentTarget);
282
+ this.#settle();
283
+ this.#owe(true);
284
+ const target = event.currentTarget;
285
+ const element = event.target;
286
+ this.#composition = { target, element, text: textOf(element) };
287
+ this.#runAbandon();
204
288
  this.#onStart?.(event);
205
289
  };
206
290
  #handleEnd = (event) => {
207
- if (event.currentTarget) this.#activeTargets.delete(event.currentTarget);
291
+ this.#runAbandon();
292
+ if (this.#composition?.target === event.currentTarget) this.#composition = null;
208
293
  this.#confirmedTarget = event.target;
209
294
  this.#onEnd?.(event);
210
295
  };
211
- #handleKeydown = () => {
296
+ #handleKeydown = (event) => {
297
+ this.#settle();
298
+ this.#runAbandon();
212
299
  this.#confirmedTarget = null;
300
+ this.#keyComposing = event.isComposing === true;
301
+ };
302
+ #handleBeforeInput = (event) => {
303
+ const keyComposing = this.#keyComposing;
304
+ this.#keyComposing = false;
305
+ this.#settle();
306
+ const { isComposing, inputType } = event;
307
+ if (this.#composition !== null && !keyComposing && !isComposing && inputType && !isCompositionInputType(inputType)) {
308
+ this.#abandon(true);
309
+ }
310
+ this.#runAbandon();
311
+ };
312
+ #handleInput = (event) => {
313
+ const composition = this.#composition;
314
+ const { isTrusted, isComposing, inputType } = event;
315
+ if (composition !== null && event.target === composition.element && (isTrusted || isComposing || isCompositionInputType(inputType))) {
316
+ composition.text = textOf(composition.element);
317
+ } else {
318
+ this.#settle();
319
+ }
320
+ this.#runAbandon();
321
+ };
322
+ #handleBlur = (event) => {
323
+ this.#settle();
324
+ this.#runAbandon();
325
+ const composition = this.#composition;
326
+ if (composition === null || composition.target === composition.element) return;
327
+ const { element } = composition;
328
+ if (!(element instanceof Node) || event.target !== element) return;
329
+ const root = element.getRootNode();
330
+ if (root.activeElement !== element) this.#composition = null;
331
+ };
332
+ #handleBeforeMorphAttribute = (event) => {
333
+ this.#settle();
334
+ const composition = this.#composition;
335
+ if (composition?.target !== event.currentTarget || event.target !== composition.element) return;
336
+ const detail = event.detail;
337
+ if (detail?.attributeName === "value") event.preventDefault();
213
338
  };
214
339
  };
215
340
 
341
+ var ListenerSet = class {
342
+ #abort = new AbortController();
343
+ add(target, type, handler, options) {
344
+ target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
345
+ }
346
+ dispose() {
347
+ this.#abort.abort();
348
+ this.#abort = new AbortController();
349
+ }
350
+ };
351
+
216
352
  var EditableController = class extends Controller {
217
353
  static targets = ["display", "input"];
218
354
  static values = {
@@ -232,17 +368,18 @@ var EditableController = class extends Controller {
232
368
  if (next instanceof Node && this.element.contains(next)) return;
233
369
  if (this.submitOnBlurValue) this.#commit(false);
234
370
  };
371
+ #listeners = new ListenerSet();
235
372
  connect() {
236
373
  this.#connected = true;
237
374
  if (this.hasInputTarget) this.#composition.observe(this.inputTarget);
238
- this.element.addEventListener("focusout", this.#onFocusOut);
375
+ this.#listeners.add(this.element, "focusout", this.#onFocusOut);
239
376
  this.#revertValue = null;
240
377
  this.#setMode("display");
241
378
  }
242
379
  disconnect() {
243
380
  this.#connected = false;
244
381
  this.#composition.disconnect();
245
- this.element.removeEventListener("focusout", this.#onFocusOut);
382
+ this.#listeners.dispose();
246
383
  }
247
384
  inputTargetConnected(input) {
248
385
  this.#composition.observe(input);
@@ -283,6 +420,7 @@ var EditableController = class extends Controller {
283
420
  this.#revertValue = null;
284
421
  }
285
422
  onDisplayKeydown(event) {
423
+ if (event.defaultPrevented) return;
286
424
  if (event.key === "F2") {
287
425
  event.preventDefault();
288
426
  this.edit();