stimeo-ui 0.16.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 (117) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +136 -0
  3. data/README.md +27 -11
  4. data/dist/cable/index.js +384 -449
  5. data/dist/controllers/accordion_controller.js +174 -55
  6. data/dist/controllers/alert_dialog_controller.js +903 -235
  7. data/dist/controllers/announcer_controller.js +238 -205
  8. data/dist/controllers/aspect_ratio_controller.js +0 -10
  9. data/dist/controllers/auto_submit_controller.js +414 -145
  10. data/dist/controllers/avatar_controller.js +185 -107
  11. data/dist/controllers/breadcrumb_controller.js +0 -130
  12. data/dist/controllers/bulk_select_controller.js +282 -58
  13. data/dist/controllers/calendar_controller.js +228 -260
  14. data/dist/controllers/carousel_controller.js +536 -436
  15. data/dist/controllers/character_counter_controller.js +493 -207
  16. data/dist/controllers/checkbox_controller.js +38 -74
  17. data/dist/controllers/clipboard_controller.js +261 -149
  18. data/dist/controllers/collapsible_controller.js +304 -120
  19. data/dist/controllers/color_picker_controller.js +178 -146
  20. data/dist/controllers/combobox_controller.js +522 -156
  21. data/dist/controllers/command_palette_controller.js +1156 -395
  22. data/dist/controllers/conditional_fields_controller.js +300 -171
  23. data/dist/controllers/confirm_controller.js +980 -262
  24. data/dist/controllers/context_menu_controller.js +346 -153
  25. data/dist/controllers/count_up_controller.js +73 -21
  26. data/dist/controllers/countdown_controller.js +281 -158
  27. data/dist/controllers/currency_input_controller.js +575 -225
  28. data/dist/controllers/data_grid_controller.js +248 -214
  29. data/dist/controllers/date_range_picker_controller.js +338 -235
  30. data/dist/controllers/dialog_controller.js +899 -237
  31. data/dist/controllers/direct_upload_controller.js +97 -167
  32. data/dist/controllers/dirty_form_controller.js +72 -69
  33. data/dist/controllers/dismissible_controller.js +196 -24
  34. data/dist/controllers/drawer_controller.js +974 -355
  35. data/dist/controllers/dropdown_controller.js +339 -96
  36. data/dist/controllers/editable_controller.js +315 -88
  37. data/dist/controllers/empty_state_controller.js +79 -58
  38. data/dist/controllers/file_dropzone_controller.js +322 -211
  39. data/dist/controllers/filter_controller.js +77 -42
  40. data/dist/controllers/flash_controller.js +238 -347
  41. data/dist/controllers/focus_controller.js +679 -240
  42. data/dist/controllers/form_field_controller.js +156 -132
  43. data/dist/controllers/form_validation_controller.js +31 -97
  44. data/dist/controllers/frame_loading_controller.js +275 -217
  45. data/dist/controllers/highlight_controller.js +107 -75
  46. data/dist/controllers/hover_card_controller.js +327 -130
  47. data/dist/controllers/idle_controller.js +271 -101
  48. data/dist/controllers/input_mask_controller.js +483 -97
  49. data/dist/controllers/intersection_controller.js +150 -106
  50. data/dist/controllers/lazy_frame_controller.js +24 -68
  51. data/dist/controllers/listbox_controller.js +523 -240
  52. data/dist/controllers/local_time_controller.js +102 -77
  53. data/dist/controllers/masonry_controller.js +80 -96
  54. data/dist/controllers/menu_controller.js +302 -188
  55. data/dist/controllers/menubar_controller.js +232 -345
  56. data/dist/controllers/meter_controller.js +417 -87
  57. data/dist/controllers/multi_select_controller.js +785 -393
  58. data/dist/controllers/navigation_menu_controller.js +190 -250
  59. data/dist/controllers/nested_form_controller.js +396 -192
  60. data/dist/controllers/network_status_controller.js +268 -62
  61. data/dist/controllers/number_input_controller.js +610 -303
  62. data/dist/controllers/optimistic_controller.js +45 -87
  63. data/dist/controllers/otp_controller.js +658 -255
  64. data/dist/controllers/overflow_indicator_controller.js +122 -113
  65. data/dist/controllers/overflow_menu_controller.js +470 -295
  66. data/dist/controllers/pagination_controller.js +332 -123
  67. data/dist/controllers/password_reveal_controller.js +392 -121
  68. data/dist/controllers/password_strength_controller.js +111 -158
  69. data/dist/controllers/persist_controller.js +165 -111
  70. data/dist/controllers/pointer_drag_controller.js +434 -188
  71. data/dist/controllers/popover_controller.js +269 -113
  72. data/dist/controllers/portal_controller.js +215 -76
  73. data/dist/controllers/preview_guard_controller.js +243 -116
  74. data/dist/controllers/progress_controller.js +391 -78
  75. data/dist/controllers/radio_group_controller.js +278 -211
  76. data/dist/controllers/range_slider_controller.js +220 -113
  77. data/dist/controllers/rating_controller.js +458 -211
  78. data/dist/controllers/read_more_controller.js +138 -63
  79. data/dist/controllers/reading_progress_controller.js +166 -137
  80. data/dist/controllers/relative_time_controller.js +211 -112
  81. data/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +103 -38
  82. data/dist/controllers/resizable_controller.js +299 -150
  83. data/dist/controllers/roving_controller.js +49 -88
  84. data/dist/controllers/scroll_area_controller.js +490 -246
  85. data/dist/controllers/scroll_restore_controller.js +14 -55
  86. data/dist/controllers/scroll_visibility_controller.js +432 -149
  87. data/dist/controllers/scrollspy_controller.js +193 -248
  88. data/dist/controllers/separator_controller.js +285 -142
  89. data/dist/controllers/sidebar_controller.js +1069 -404
  90. data/dist/controllers/skeleton_controller.js +259 -101
  91. data/dist/controllers/slider_controller.js +187 -86
  92. data/dist/controllers/smart_sticky_header_controller.js +173 -66
  93. data/dist/controllers/sortable_controller.js +26 -125
  94. data/dist/controllers/spinner_controller.js +288 -173
  95. data/dist/controllers/step_indicator_controller.js +105 -46
  96. data/dist/controllers/stepper_controller.js +120 -73
  97. data/dist/controllers/stick_to_bottom_controller.js +275 -140
  98. data/dist/controllers/sticky_observer_controller.js +220 -49
  99. data/dist/controllers/submit_once_controller.js +376 -227
  100. data/dist/controllers/switch_controller.js +201 -84
  101. data/dist/controllers/tabs_controller.js +41 -30
  102. data/dist/controllers/tags_input_controller.js +293 -173
  103. data/dist/controllers/textarea_autosize_controller.js +108 -74
  104. data/dist/controllers/theme_controller.js +140 -116
  105. data/dist/controllers/time_picker_controller.js +331 -127
  106. data/dist/controllers/toast_controller.js +244 -324
  107. data/dist/controllers/toggle_group_controller.js +252 -191
  108. data/dist/controllers/toolbar_controller.js +219 -120
  109. data/dist/controllers/tooltip_controller.js +158 -124
  110. data/dist/controllers/transition_controller.js +123 -119
  111. data/dist/controllers/tree_view_controller.js +283 -369
  112. data/dist/index.js +8573 -10410
  113. data/dist/positioning/index.js +154 -47
  114. data/lib/generators/stimeo/install/install_generator.rb +7 -2
  115. data/lib/generators/stimeo/install/templates/stimeo.js +19 -6
  116. data/lib/stimeo/ui/version.rb +1 -1
  117. metadata +3 -3
@@ -1,26 +1,17 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
3
- // src/controllers/checkbox_controller.ts
4
-
5
- // src/utils/form_reset_watcher.ts
6
3
  var FormResetWatcher = class {
7
4
  #owns;
8
5
  #onReset;
9
6
  #frames = /* @__PURE__ */ new Set();
10
7
  #generation = 0;
11
- /**
12
- * @param owns - whether `form` owns a control this controller derives from.
13
- * @param onReset - the reconciliation pass, run once per honoured reset.
14
- */
15
8
  constructor(owns, onReset) {
16
9
  this.#owns = owns;
17
10
  this.#onReset = onReset;
18
11
  }
19
- /** Subscribes to `reset` at the document; call from `connect()`. Idempotent. */
20
12
  observe() {
21
13
  document.addEventListener("reset", this.#handleReset, true);
22
14
  }
23
- /** Unsubscribes and drops every pending pass; call from `disconnect()`. */
24
15
  disconnect() {
25
16
  document.removeEventListener("reset", this.#handleReset, true);
26
17
  this.#generation += 1;
@@ -44,57 +35,41 @@ var FormResetWatcher = class {
44
35
  this.#frames.add(frame);
45
36
  });
46
37
  };
47
- /** Runs the pass unless a listener cancelled the reset before it landed. */
48
38
  #settle(event) {
49
39
  if (!event.defaultPrevented) this.#onReset();
50
40
  }
51
41
  };
52
42
 
53
- // src/utils/listener_set.ts
54
43
  var ListenerSet = class {
55
- /** The generation every `add` joins until the next `dispose()`. */
56
44
  #abort = new AbortController();
57
- /**
58
- * Attaches `handler` to the open generation, exactly as the caller spelled it.
59
- *
60
- * The set supplies the signal, so `options` carries everything else the DOM
61
- * accepts — `capture` included, which has to match at release time and no
62
- * longer has a second place to drift from.
63
- */
64
45
  add(target, type, handler, options) {
65
46
  target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
66
47
  }
67
- /**
68
- * Releases every listener of the open generation, synchronously, and opens the
69
- * next one. Idempotent, and safe before anything has been added.
70
- */
71
48
  dispose() {
72
49
  this.#abort.abort();
73
50
  this.#abort = new AbortController();
74
51
  }
75
52
  };
76
53
 
77
- // src/utils/microtask_coalescer.ts
78
54
  var MicrotaskCoalescer = class {
79
55
  #run;
80
56
  #queued = false;
81
57
  #active = false;
82
58
  #generation = 0;
83
- /** @param run - the single reconciliation pass, invoked at most once per batch. */
84
59
  constructor(run) {
85
60
  this.#run = run;
86
61
  }
87
- /** Opens the window in which {@link schedule} is honoured; call from `connect()`. */
88
62
  activate() {
89
63
  this.#active = true;
90
64
  }
91
- /** Closes the window and drops any pending pass; call from `disconnect()`. */
92
65
  cancel() {
93
66
  this.#active = false;
94
67
  this.#queued = false;
95
68
  this.#generation += 1;
96
69
  }
97
- /** Requests one pass after the batch settles. Idempotent; inert outside the window. */
70
+ get pending() {
71
+ return this.#queued;
72
+ }
98
73
  schedule() {
99
74
  if (!this.#active || this.#queued) return;
100
75
  this.#queued = true;
@@ -107,82 +82,95 @@ var MicrotaskCoalescer = class {
107
82
  }
108
83
  };
109
84
 
110
- // src/controllers/checkbox_controller.ts
85
+ var MorphRenderWatcher = class {
86
+ #listeners = new ListenerSet();
87
+ #pass;
88
+ #element = null;
89
+ #onMorph = () => this.#pass.schedule();
90
+ constructor(run) {
91
+ this.#pass = new MicrotaskCoalescer(run);
92
+ }
93
+ observe(element) {
94
+ if (this.#element === element) return;
95
+ this.disconnect();
96
+ this.#element = element;
97
+ this.#pass.activate();
98
+ this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
99
+ }
100
+ schedule() {
101
+ this.#pass.schedule();
102
+ }
103
+ get pending() {
104
+ return this.#pass.pending;
105
+ }
106
+ disconnect() {
107
+ this.#listeners.dispose();
108
+ this.#pass.cancel();
109
+ this.#element = null;
110
+ }
111
+ };
112
+
111
113
  var CheckboxController = class extends Controller {
112
114
  static targets = ["parent", "child"];
113
115
  static actions = ["onChildChange", "onParentChange"];
114
116
  static events = ["change", "reconcile"];
115
- /** Collapses every lifecycle signal from one DOM update into one derived pass. */
116
- #reconcile = new MicrotaskCoalescer(() => this.#reconcileFromChildren());
117
- #listeners = new ListenerSet();
117
+ #reconcile = new MorphRenderWatcher(() => this.#reconcileFromChildren());
118
118
  #formReset = new FormResetWatcher(
119
119
  (form) => this.#hasCheckboxOwnedBy(form),
120
120
  () => this.#reconcile.schedule()
121
121
  );
122
- /** Aggregate this root last settled on, so a derived repair is reported once. */
123
122
  #committedState = null;
124
- /** Watches authored checked-attribute changes on retained target elements. */
125
123
  #checkedObserver = new MutationObserver((records) => {
126
124
  if (records.some((record) => this.#isManagedCheckbox(record.target))) {
127
125
  this.#reconcile.schedule();
128
126
  }
129
127
  });
130
- /** Reflects the initial aggregate and starts retained-DOM reconciliation. */
131
128
  connect() {
132
- this.#reconcile.activate();
133
129
  this.#syncFromChildren();
130
+ this.#reconcile.observe(this.element);
134
131
  this.#checkedObserver.observe(this.element, {
135
132
  attributes: true,
136
133
  attributeFilter: ["checked"],
137
134
  subtree: true
138
135
  });
139
- this.#listeners.add(this.element, "turbo:morph-element", this.#onMorph);
140
136
  this.#formReset.observe();
141
137
  }
142
- /** Releases the observer, global reset listener, and every pending reconciliation. */
143
138
  disconnect() {
144
- this.#reconcile.cancel();
139
+ this.#reconcile.disconnect();
145
140
  this.#checkedObserver.disconnect();
146
- this.#listeners.dispose();
147
141
  this.#formReset.disconnect();
148
142
  }
149
- /** Reconciles the aggregate for a parent added or replaced at runtime. */
150
143
  parentTargetConnected() {
151
144
  this.#reconcile.schedule();
152
145
  }
153
- /** Reconciles the aggregate after a parent target leaves the group. */
154
146
  parentTargetDisconnected() {
155
147
  this.#reconcile.schedule();
156
148
  }
157
- /** Reconciles the aggregate for a child added at runtime. */
158
149
  childTargetConnected() {
159
150
  this.#reconcile.schedule();
160
151
  }
161
- /** Reconciles the aggregate after a child leaves the group. */
162
152
  childTargetDisconnected() {
163
153
  this.#reconcile.schedule();
164
154
  }
165
- /** Cascades the parent's state to every child. Bound via `data-action` (change). */
166
155
  onParentChange() {
167
156
  if (!this.hasParentTarget) return;
157
+ const previous = this.#committedState;
168
158
  const checked = this.parentTarget.checked;
169
159
  for (const child of this.childTargets) {
170
160
  child.checked = checked;
171
161
  }
172
162
  this.#reflect(checked ? "all" : "none", true);
163
+ if (this.#committedState === previous) return;
173
164
  const detail = this.#settledDetail();
174
165
  if (detail) this.dispatch("change", { detail });
175
166
  }
176
- /** Recomputes the parent from its children. Bound via `data-action` (change). */
177
167
  onChildChange() {
168
+ const previous = this.#committedState;
178
169
  this.#syncFromChildren();
170
+ if (this.#committedState === previous) return;
179
171
  const detail = this.#settledDetail();
180
172
  if (detail) this.dispatch("change", { detail });
181
173
  }
182
- /**
183
- * Announces an aggregate this pass derived rather than the user. `change` stays
184
- * reserved for the two public actions, so automation never reads a repair as an edit.
185
- */
186
174
  #reconcileFromChildren() {
187
175
  const previous = this.#committedState;
188
176
  this.#syncFromChildren();
@@ -190,20 +178,9 @@ var CheckboxController = class extends Controller {
190
178
  const detail = this.#settledDetail();
191
179
  if (detail) this.dispatch("reconcile", { detail });
192
180
  }
193
- /**
194
- * Derives the parent's `checked`/`indeterminate` and the root `data-state` from
195
- * the children. Writing state and reporting it are separate so the caller — not
196
- * a flag threaded through the write — decides which event describes the cause.
197
- */
198
181
  #syncFromChildren() {
199
182
  this.#reflect(this.#aggregate(), this.childTargets.length > 0);
200
183
  }
201
- /**
202
- * Reflects one aggregate state.
203
- *
204
- * @param writeParent - whether the state is authoritative over the `parent`
205
- * target's own `checked` / `indeterminate`.
206
- */
207
184
  #reflect(state, writeParent) {
208
185
  if (writeParent && this.hasParentTarget) {
209
186
  this.parentTarget.checked = state === "all";
@@ -212,29 +189,17 @@ var CheckboxController = class extends Controller {
212
189
  this.element.setAttribute("data-state", state);
213
190
  this.#committedState = state;
214
191
  }
215
- /** The settled aggregate as event detail, or `null` before anything has settled. */
216
192
  #settledDetail() {
217
193
  const state = this.#committedState;
218
194
  if (state === null) return null;
219
195
  return { checked: state === "all", indeterminate: state === "partial", state };
220
196
  }
221
- /** Reconciles retained targets after Turbo has finished morphing their live state. */
222
- #onMorph = () => {
223
- this.#reconcile.schedule();
224
- };
225
- /** Whether a form owns at least one current parent or child target. */
226
197
  #hasCheckboxOwnedBy(form) {
227
198
  return [...this.parentTargets, ...this.childTargets].some((checkbox) => checkbox.form === form);
228
199
  }
229
- /** Whether an observed attribute mutation belongs to this controller's target set. */
230
200
  #isManagedCheckbox(node) {
231
201
  return this.parentTargets.some((checkbox) => checkbox === node) || this.childTargets.some((checkbox) => checkbox === node);
232
202
  }
233
- /**
234
- * Computes the aggregate state. With children it counts them; with none it
235
- * reads the parent so a lone tri-state checkbox still reports a state without
236
- * its externally-set `indeterminate` being clobbered.
237
- */
238
203
  #aggregate() {
239
204
  const children = this.childTargets;
240
205
  if (children.length === 0) {
@@ -249,5 +214,4 @@ var CheckboxController = class extends Controller {
249
214
  };
250
215
 
251
216
  export { CheckboxController };
252
- //# sourceMappingURL=checkbox_controller.js.map
253
217
  //# sourceMappingURL=checkbox_controller.js.map