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,8 +1,12 @@
1
1
  import { Controller } from '@hotwired/stimulus';
2
2
 
3
- // src/controllers/empty_state_controller.ts
3
+ function fillTemplate(template, values) {
4
+ return template.replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (match, name) => {
5
+ const replacement = Object.hasOwn(values, name) ? values[name] : void 0;
6
+ return replacement === void 0 ? match : String(replacement);
7
+ });
8
+ }
4
9
 
5
- // src/utils/announce.ts
6
10
  function announce(message, options = {}) {
7
11
  const text = message.trim();
8
12
  if (text.length === 0) return;
@@ -12,14 +16,77 @@ function announce(message, options = {}) {
12
16
  })
13
17
  );
14
18
  }
15
- function fillTemplate(template, values) {
16
- return template.replace(/\{([a-zA-Z][a-zA-Z0-9]*)\}/g, (match, name) => {
17
- const replacement = values[name];
18
- return replacement === void 0 ? match : String(replacement);
19
- });
20
- }
21
19
 
22
- // src/controllers/empty_state_controller.ts
20
+ var ListenerSet = class {
21
+ #abort = new AbortController();
22
+ add(target, type, handler, options) {
23
+ target.addEventListener(type, handler, { ...options, signal: this.#abort.signal });
24
+ }
25
+ dispose() {
26
+ this.#abort.abort();
27
+ this.#abort = new AbortController();
28
+ }
29
+ };
30
+
31
+ var MicrotaskCoalescer = class {
32
+ #run;
33
+ #queued = false;
34
+ #active = false;
35
+ #generation = 0;
36
+ constructor(run) {
37
+ this.#run = run;
38
+ }
39
+ activate() {
40
+ this.#active = true;
41
+ }
42
+ cancel() {
43
+ this.#active = false;
44
+ this.#queued = false;
45
+ this.#generation += 1;
46
+ }
47
+ get pending() {
48
+ return this.#queued;
49
+ }
50
+ schedule() {
51
+ if (!this.#active || this.#queued) return;
52
+ this.#queued = true;
53
+ const generation = this.#generation;
54
+ queueMicrotask(() => {
55
+ if (generation !== this.#generation || !this.#queued || !this.#active) return;
56
+ this.#queued = false;
57
+ this.#run();
58
+ });
59
+ }
60
+ };
61
+
62
+ var MorphRenderWatcher = class {
63
+ #listeners = new ListenerSet();
64
+ #pass;
65
+ #element = null;
66
+ #onMorph = () => this.#pass.schedule();
67
+ constructor(run) {
68
+ this.#pass = new MicrotaskCoalescer(run);
69
+ }
70
+ observe(element) {
71
+ if (this.#element === element) return;
72
+ this.disconnect();
73
+ this.#element = element;
74
+ this.#pass.activate();
75
+ this.#listeners.add(element, "turbo:morph-element", this.#onMorph);
76
+ }
77
+ schedule() {
78
+ this.#pass.schedule();
79
+ }
80
+ get pending() {
81
+ return this.#pass.pending;
82
+ }
83
+ disconnect() {
84
+ this.#listeners.dispose();
85
+ this.#pass.cancel();
86
+ this.#element = null;
87
+ }
88
+ };
89
+
23
90
  var EmptyStateController = class extends Controller {
24
91
  static targets = ["list", "empty"];
25
92
  static values = {
@@ -29,68 +96,40 @@ var EmptyStateController = class extends Controller {
29
96
  };
30
97
  static events = ["change"];
31
98
  #observer = null;
32
- /** Whether the controller is between `connect()` and `disconnect()`. */
33
99
  #connected = false;
34
- /** Last applied empty state; `null` until the first sync so connect emits nothing. */
35
100
  #empty = null;
101
+ #morphRender = new MorphRenderWatcher(() => this.#resync());
36
102
  connect() {
103
+ this.#morphRender.observe(this.element);
37
104
  this.#connected = true;
38
105
  this.#syncObservation();
39
106
  this.#update();
40
107
  }
41
108
  disconnect() {
109
+ this.#morphRender.disconnect();
42
110
  this.#connected = false;
43
111
  this.#stopObserving();
44
112
  }
45
- /** Follows a `list` element swapped in at runtime (Turbo Stream `replace` / morph). */
46
113
  listTargetConnected() {
47
114
  this.#resync();
48
115
  }
49
- /** Releases the observation when the `list` element leaves the target set. */
50
116
  listTargetDisconnected() {
51
117
  this.#resync();
52
118
  }
53
- /** Syncs an `empty` element that arrives — or is replaced — at runtime. */
54
119
  emptyTargetConnected() {
55
120
  this.#resync();
56
121
  }
57
- /**
58
- * Syncs the `empty` element that remains when one leaves the target set. A
59
- * single-target getter resolves to the first `empty` element in document order,
60
- * so a swap that inserts the replacement *before* removing the original (Turbo
61
- * Stream `after` / `before` / `append` followed by `remove`) leaves the
62
- * replacement untouched until the original goes — this callback is that moment.
63
- */
64
122
  emptyTargetDisconnected() {
65
123
  this.#resync();
66
124
  }
67
- /** Re-renders when application code (or a Turbo morph) changes `itemSelector` at runtime. */
68
125
  itemSelectorValueChanged() {
69
126
  this.#resync();
70
127
  }
71
- /**
72
- * Re-points the observation and re-renders after a target or selector change.
73
- * The `#connected` guard is load-bearing: Stimulus runs value and target
74
- * callbacks for the initial markup *before* `connect()` and runs target
75
- * callbacks during teardown *after* `disconnect()`, and re-observing there
76
- * would outlive the controller.
77
- */
78
128
  #resync() {
79
129
  if (!this.#connected) return;
80
130
  this.#syncObservation();
81
131
  this.#update();
82
132
  }
83
- /**
84
- * Points the mutation observation at the current `list` target — re-resolved on
85
- * every sync rather than captured at connect, so an element swapped in at
86
- * runtime is observed instead of the detached original.
87
- *
88
- * The observation covers exactly what the count predicate reads. With no
89
- * `itemSelector` the count is the child element count, which only `childList`
90
- * can change. With one, the predicate reads the children themselves, so
91
- * attribute and descendant mutations are watched too — and the controller's own
92
- * writes are filtered back out, or toggling `hidden` would re-enter the render.
93
- */
94
133
  #syncObservation() {
95
134
  this.#stopObserving();
96
135
  if (!this.hasListTarget || typeof MutationObserver === "undefined") return;
@@ -108,21 +147,11 @@ var EmptyStateController = class extends Controller {
108
147
  this.#observer?.disconnect();
109
148
  this.#observer = null;
110
149
  }
111
- /**
112
- * Whether a mutation can change the item count. An attribute written on a
113
- * target this controller owns is its own echo — `hidden` on `list` / `empty`,
114
- * and the hooks on the controller element when the list *is* that element.
115
- */
116
150
  #affectsCount(record) {
117
151
  if (record.type !== "attributes") return true;
118
152
  const own = record.target === this.listTarget || this.hasEmptyTarget && record.target === this.emptyTarget;
119
153
  return !own;
120
154
  }
121
- /**
122
- * Renders the count, then reports a crossed boundary. The announcement copy is
123
- * read here rather than while rendering: it is the wording of the report, not
124
- * an input to what is displayed.
125
- */
126
155
  #update() {
127
156
  const count = this.#render();
128
157
  if (count === null) return;
@@ -135,12 +164,6 @@ var EmptyStateController = class extends Controller {
135
164
  fillTemplate(empty ? this.announceTextValue : this.announceFilledTextValue, { count })
136
165
  );
137
166
  }
138
- /**
139
- * Syncs visibility and the state hooks to the current item count, and returns
140
- * it. `null` when there is no `list` target to count.
141
- *
142
- * @stimeoRenderRoot
143
- */
144
167
  #render() {
145
168
  if (!this.hasListTarget) return null;
146
169
  const count = this.#count();
@@ -155,7 +178,6 @@ var EmptyStateController = class extends Controller {
155
178
  if (this.hasEmptyTarget) this.emptyTarget.hidden = !empty;
156
179
  return count;
157
180
  }
158
- /** Item count: element children matching `itemSelector`, or all element children. */
159
181
  #count() {
160
182
  const selector = this.itemSelectorValue;
161
183
  if (selector.length === 0) return this.listTarget.childElementCount;
@@ -168,5 +190,4 @@ var EmptyStateController = class extends Controller {
168
190
  };
169
191
 
170
192
  export { EmptyStateController };
171
- //# sourceMappingURL=empty_state_controller.js.map
172
193
  //# sourceMappingURL=empty_state_controller.js.map