stimeo-ui 0.16.0 → 0.17.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +8 -1
- data/dist/cable/index.js +363 -436
- data/dist/controllers/accordion_controller.js +166 -55
- data/dist/controllers/alert_dialog_controller.js +862 -221
- data/dist/controllers/announcer_controller.js +135 -198
- data/dist/controllers/aspect_ratio_controller.js +0 -10
- data/dist/controllers/auto_submit_controller.js +271 -127
- data/dist/controllers/avatar_controller.js +171 -105
- data/dist/controllers/breadcrumb_controller.js +0 -130
- data/dist/controllers/bulk_select_controller.js +262 -52
- data/dist/controllers/calendar_controller.js +175 -209
- data/dist/controllers/carousel_controller.js +461 -399
- data/dist/controllers/character_counter_controller.js +246 -156
- data/dist/controllers/checkbox_controller.js +32 -74
- data/dist/controllers/clipboard_controller.js +168 -147
- data/dist/controllers/collapsible_controller.js +301 -120
- data/dist/controllers/color_picker_controller.js +149 -139
- data/dist/controllers/combobox_controller.js +360 -133
- data/dist/controllers/command_palette_controller.js +970 -358
- data/dist/controllers/conditional_fields_controller.js +166 -124
- data/dist/controllers/confirm_controller.js +939 -248
- data/dist/controllers/context_menu_controller.js +256 -128
- data/dist/controllers/count_up_controller.js +73 -21
- data/dist/controllers/countdown_controller.js +183 -148
- data/dist/controllers/currency_input_controller.js +134 -158
- data/dist/controllers/data_grid_controller.js +114 -186
- data/dist/controllers/date_range_picker_controller.js +288 -206
- data/dist/controllers/dialog_controller.js +858 -223
- data/dist/controllers/direct_upload_controller.js +73 -153
- data/dist/controllers/dirty_form_controller.js +14 -48
- data/dist/controllers/dismissible_controller.js +175 -21
- data/dist/controllers/drawer_controller.js +933 -341
- data/dist/controllers/dropdown_controller.js +312 -82
- data/dist/controllers/editable_controller.js +158 -68
- data/dist/controllers/empty_state_controller.js +67 -53
- data/dist/controllers/file_dropzone_controller.js +311 -207
- data/dist/controllers/filter_controller.js +67 -39
- data/dist/controllers/flash_controller.js +172 -314
- data/dist/controllers/focus_controller.js +654 -240
- data/dist/controllers/form_field_controller.js +147 -132
- data/dist/controllers/form_validation_controller.js +13 -86
- data/dist/controllers/frame_loading_controller.js +264 -213
- data/dist/controllers/highlight_controller.js +107 -75
- data/dist/controllers/hover_card_controller.js +309 -118
- data/dist/controllers/idle_controller.js +267 -101
- data/dist/controllers/input_mask_controller.js +71 -72
- data/dist/controllers/intersection_controller.js +147 -106
- data/dist/controllers/lazy_frame_controller.js +9 -65
- data/dist/controllers/listbox_controller.js +306 -204
- data/dist/controllers/local_time_controller.js +54 -64
- data/dist/controllers/masonry_controller.js +70 -93
- data/dist/controllers/menu_controller.js +214 -156
- data/dist/controllers/menubar_controller.js +170 -329
- data/dist/controllers/meter_controller.js +151 -67
- data/dist/controllers/multi_select_controller.js +593 -358
- data/dist/controllers/navigation_menu_controller.js +124 -232
- data/dist/controllers/nested_form_controller.js +352 -182
- data/dist/controllers/network_status_controller.js +242 -54
- data/dist/controllers/number_input_controller.js +320 -263
- data/dist/controllers/optimistic_controller.js +16 -76
- data/dist/controllers/otp_controller.js +198 -193
- data/dist/controllers/overflow_indicator_controller.js +116 -113
- data/dist/controllers/overflow_menu_controller.js +343 -283
- data/dist/controllers/pagination_controller.js +295 -119
- data/dist/controllers/password_reveal_controller.js +389 -121
- data/dist/controllers/password_strength_controller.js +99 -153
- data/dist/controllers/persist_controller.js +237 -103
- data/dist/controllers/pointer_drag_controller.js +185 -165
- data/dist/controllers/popover_controller.js +236 -97
- data/dist/controllers/portal_controller.js +209 -76
- data/dist/controllers/preview_guard_controller.js +232 -116
- data/dist/controllers/progress_controller.js +125 -56
- data/dist/controllers/radio_group_controller.js +117 -137
- data/dist/controllers/range_slider_controller.js +192 -105
- data/dist/controllers/rating_controller.js +418 -207
- data/dist/controllers/read_more_controller.js +134 -63
- data/dist/controllers/reading_progress_controller.js +147 -135
- data/dist/controllers/relative_time_controller.js +145 -110
- data/dist/controllers/{reset_before_cache_controller.js → reset_on_restore_controller.js} +97 -38
- data/dist/controllers/resizable_controller.js +255 -139
- data/dist/controllers/roving_controller.js +39 -84
- data/dist/controllers/scroll_area_controller.js +428 -225
- data/dist/controllers/scroll_restore_controller.js +0 -53
- data/dist/controllers/scroll_visibility_controller.js +395 -145
- data/dist/controllers/scrollspy_controller.js +181 -242
- data/dist/controllers/separator_controller.js +267 -140
- data/dist/controllers/sidebar_controller.js +1023 -386
- data/dist/controllers/skeleton_controller.js +248 -97
- data/dist/controllers/slider_controller.js +159 -79
- data/dist/controllers/smart_sticky_header_controller.js +162 -63
- data/dist/controllers/sortable_controller.js +0 -112
- data/dist/controllers/spinner_controller.js +277 -169
- data/dist/controllers/step_indicator_controller.js +99 -46
- data/dist/controllers/stepper_controller.js +114 -73
- data/dist/controllers/stick_to_bottom_controller.js +262 -138
- data/dist/controllers/sticky_observer_controller.js +214 -49
- data/dist/controllers/submit_once_controller.js +294 -205
- data/dist/controllers/switch_controller.js +33 -60
- data/dist/controllers/tabs_controller.js +35 -29
- data/dist/controllers/tags_input_controller.js +136 -145
- data/dist/controllers/textarea_autosize_controller.js +71 -58
- data/dist/controllers/theme_controller.js +130 -112
- data/dist/controllers/time_picker_controller.js +146 -80
- data/dist/controllers/toast_controller.js +186 -297
- data/dist/controllers/toggle_group_controller.js +95 -136
- data/dist/controllers/toolbar_controller.js +68 -98
- data/dist/controllers/tooltip_controller.js +158 -124
- data/dist/controllers/transition_controller.js +123 -119
- data/dist/controllers/tree_view_controller.js +150 -345
- data/dist/index.js +6370 -9346
- data/dist/positioning/index.js +148 -47
- data/lib/stimeo/ui/version.rb +1 -1
- metadata +3 -3
|
@@ -1,44 +1,25 @@
|
|
|
1
1
|
import { Controller } from '@hotwired/stimulus';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
4
4
|
|
|
5
|
-
// src/utils/safe_timeout.ts
|
|
6
5
|
var TimerRegistry = class {
|
|
7
|
-
/** Live timer ids that have not yet been cleared (or, for timeouts, fired). */
|
|
8
6
|
ids = /* @__PURE__ */ new Set();
|
|
9
|
-
/**
|
|
10
|
-
* Cancels a single tracked timer.
|
|
11
|
-
*
|
|
12
|
-
* No-ops if the id is unknown (already cleared, fired, or never owned by this
|
|
13
|
-
* registry), so callers can clear defensively without guarding.
|
|
14
|
-
*/
|
|
15
7
|
clear(id) {
|
|
16
8
|
if (this.ids.delete(id)) {
|
|
17
9
|
this.cancel(id);
|
|
18
10
|
}
|
|
19
11
|
}
|
|
20
|
-
/**
|
|
21
|
-
* Cancels every tracked timer. Call this from a controller's `disconnect()`
|
|
22
|
-
* to guarantee no timer outlives the element.
|
|
23
|
-
*/
|
|
24
12
|
clearAll() {
|
|
25
13
|
for (const id of this.ids) {
|
|
26
14
|
this.cancel(id);
|
|
27
15
|
}
|
|
28
16
|
this.ids.clear();
|
|
29
17
|
}
|
|
30
|
-
/** Number of timers currently tracked (pending). */
|
|
31
18
|
get size() {
|
|
32
19
|
return this.ids.size;
|
|
33
20
|
}
|
|
34
21
|
};
|
|
35
22
|
var SafeTimeout = class extends TimerRegistry {
|
|
36
|
-
/**
|
|
37
|
-
* Schedules `callback` after `delay` ms and returns the timer id.
|
|
38
|
-
*
|
|
39
|
-
* The id is removed from the registry automatically when the timeout fires,
|
|
40
|
-
* so {@link TimerRegistry.size | size} reflects only still-pending timers.
|
|
41
|
-
*/
|
|
42
23
|
set(callback, delay) {
|
|
43
24
|
const id = this.schedule(() => {
|
|
44
25
|
this.ids.delete(id);
|
|
@@ -55,16 +36,9 @@ var SafeTimeout = class extends TimerRegistry {
|
|
|
55
36
|
}
|
|
56
37
|
};
|
|
57
38
|
|
|
58
|
-
// src/utils/keyed_timers.ts
|
|
59
39
|
var KeyedTimers = class {
|
|
60
40
|
#timers = new SafeTimeout();
|
|
61
|
-
/** The pending timer of each key; an entry lives exactly as long as its timer. */
|
|
62
41
|
#pending = /* @__PURE__ */ new Map();
|
|
63
|
-
/**
|
|
64
|
-
* Arms `callback` after `delay` ms for `key`, cancelling the timer `key` had
|
|
65
|
-
* pending. The entry is dropped before the callback runs, so the callback sees
|
|
66
|
-
* the key unarmed and may arm it again for the next round.
|
|
67
|
-
*/
|
|
68
42
|
set(key, callback, delay) {
|
|
69
43
|
this.clear(key);
|
|
70
44
|
const id = this.#timers.set(() => {
|
|
@@ -73,86 +47,145 @@ var KeyedTimers = class {
|
|
|
73
47
|
}, delay);
|
|
74
48
|
this.#pending.set(key, id);
|
|
75
49
|
}
|
|
76
|
-
/**
|
|
77
|
-
* Cancels `key`'s pending timer, if it has one.
|
|
78
|
-
*
|
|
79
|
-
* A timer id is a positive integer, so `-1` stands for "nothing pending" and
|
|
80
|
-
* the registry ignores an id it does not own — the unarmed case needs no
|
|
81
|
-
* branch of its own, and no other key's timer can be reached from here.
|
|
82
|
-
*/
|
|
83
50
|
clear(key) {
|
|
84
51
|
this.#timers.clear(this.#pending.get(key) ?? -1);
|
|
85
52
|
this.#pending.delete(key);
|
|
86
53
|
}
|
|
87
|
-
/**
|
|
88
|
-
* Cancels every pending timer and forgets every key. Call this from a
|
|
89
|
-
* controller's `disconnect()` so no timer, and no entry, outlives the element.
|
|
90
|
-
*/
|
|
91
54
|
clearAll() {
|
|
92
55
|
this.#timers.clearAll();
|
|
93
56
|
this.#pending.clear();
|
|
94
57
|
}
|
|
95
|
-
/** Whether `key` has a timer pending. */
|
|
96
58
|
has(key) {
|
|
97
59
|
return this.#pending.has(key);
|
|
98
60
|
}
|
|
99
61
|
};
|
|
100
62
|
|
|
101
|
-
|
|
63
|
+
var NUMBER_BOUNDS = {
|
|
64
|
+
timer: { finite: true, min: 0, max: MAX_TIMER_DELAY_MS }};
|
|
65
|
+
function matchesNumberBounds(value, bounds) {
|
|
66
|
+
if (!Number.isFinite(value)) {
|
|
67
|
+
const direction = value === Infinity ? "positive" : value === -Infinity ? "negative" : null;
|
|
68
|
+
if (direction === null) return false;
|
|
69
|
+
if (bounds.allowInfinity !== "both" && bounds.allowInfinity !== direction) return false;
|
|
70
|
+
}
|
|
71
|
+
if (bounds.min !== void 0 && value < bounds.min) return false;
|
|
72
|
+
if (bounds.max !== void 0 && value > bounds.max) return false;
|
|
73
|
+
if (bounds.exclusiveMin !== void 0 && value <= bounds.exclusiveMin) return false;
|
|
74
|
+
if (bounds.integer && !Number.isInteger(value)) return false;
|
|
75
|
+
if (bounds.allowedValues !== void 0 && !bounds.allowedValues.includes(value)) return false;
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function readNumber(raw, fallback, bounds) {
|
|
80
|
+
return matchesNumberBounds(raw, bounds) ? raw : fallback;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
var NumberValueReader = class {
|
|
84
|
+
#lastRejected = /* @__PURE__ */ new Map();
|
|
85
|
+
read(owner, name, raw, fallback, bounds) {
|
|
86
|
+
const resolved = readNumber(raw, fallback, bounds);
|
|
87
|
+
if (matchesNumberBounds(raw, bounds)) {
|
|
88
|
+
this.#lastRejected.delete(name);
|
|
89
|
+
return resolved;
|
|
90
|
+
}
|
|
91
|
+
const attribute = `data-${owner.identifier}-${name.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}-value`;
|
|
92
|
+
const literal = owner.element.getAttribute(attribute);
|
|
93
|
+
if (literal === null) {
|
|
94
|
+
this.#lastRejected.delete(name);
|
|
95
|
+
return resolved;
|
|
96
|
+
}
|
|
97
|
+
if (this.#lastRejected.get(name) !== literal) {
|
|
98
|
+
this.#lastRejected.set(name, literal);
|
|
99
|
+
console.warn(
|
|
100
|
+
`Stimeo UI: "${owner.identifier}" has an invalid number Value "${name}" declaration ${JSON.stringify(literal)}; using ${fallback}.`
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return resolved;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
102
107
|
function prefersReducedMotion() {
|
|
103
108
|
return typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
104
109
|
}
|
|
105
110
|
|
|
106
|
-
|
|
111
|
+
function sharedRegistry(key, create) {
|
|
112
|
+
const symbol = Symbol.for(key);
|
|
113
|
+
const scope = globalThis;
|
|
114
|
+
const existing = scope[symbol];
|
|
115
|
+
if (existing !== void 0) return existing;
|
|
116
|
+
const registry = create();
|
|
117
|
+
Object.defineProperty(globalThis, symbol, { value: registry });
|
|
118
|
+
return registry;
|
|
119
|
+
}
|
|
120
|
+
|
|
107
121
|
var TransientHooks = class {
|
|
108
122
|
#attributes;
|
|
109
123
|
constructor(options) {
|
|
110
124
|
this.#attributes = options.attributes;
|
|
111
125
|
}
|
|
112
|
-
/** Drops the declared hooks from `element`; what it carries besides stays. */
|
|
113
126
|
reset(element) {
|
|
114
127
|
for (const attribute of this.#attributes) element.removeAttribute(attribute);
|
|
115
128
|
}
|
|
116
129
|
};
|
|
117
130
|
|
|
118
|
-
// src/controllers/highlight_controller.ts
|
|
119
131
|
var TRANSIENT = new TransientHooks({ attributes: ["data-highlight"] });
|
|
120
|
-
var hookOwners =
|
|
121
|
-
|
|
132
|
+
var hookOwners = sharedRegistry(
|
|
133
|
+
"stimeo-ui.highlight.registry.v1",
|
|
134
|
+
() => /* @__PURE__ */ new WeakMap()
|
|
135
|
+
);
|
|
136
|
+
var HighlightController = class _HighlightController extends Controller {
|
|
137
|
+
#numbers = new NumberValueReader();
|
|
122
138
|
static values = {
|
|
123
139
|
duration: { type: Number, default: 1500 },
|
|
124
140
|
observe: { type: Boolean, default: false }
|
|
125
141
|
};
|
|
142
|
+
static valueConstraints = {
|
|
143
|
+
duration: NUMBER_BOUNDS.timer
|
|
144
|
+
};
|
|
126
145
|
static events = ["start", "end"];
|
|
127
|
-
/**
|
|
128
|
-
* The removal timer this connection has outstanding for each element. Which
|
|
129
|
-
* connection owns an element's hook is answered by the shared owner registry above.
|
|
130
|
-
*/
|
|
131
146
|
#removal = new KeyedTimers();
|
|
132
147
|
#observer = null;
|
|
148
|
+
#watching = false;
|
|
149
|
+
#connected = false;
|
|
133
150
|
connect() {
|
|
134
151
|
this.#clearArrivedHook(this.element);
|
|
152
|
+
this.#connected = true;
|
|
135
153
|
if (this.observeValue) {
|
|
136
|
-
|
|
137
|
-
if (typeof MutationObserver !== "undefined") {
|
|
138
|
-
this.#observer = new MutationObserver((mutations) => this.#onMutations(mutations));
|
|
139
|
-
this.#observer.observe(this.element, { childList: true });
|
|
140
|
-
}
|
|
154
|
+
this.#watchChildren();
|
|
141
155
|
return;
|
|
142
156
|
}
|
|
143
157
|
this.#highlight(this.element);
|
|
144
158
|
}
|
|
145
159
|
disconnect() {
|
|
160
|
+
this.#connected = false;
|
|
161
|
+
this.#stopWatching();
|
|
162
|
+
this.#removal.clearAll();
|
|
163
|
+
}
|
|
164
|
+
observeValueChanged() {
|
|
165
|
+
if (!this.#connected || this.observeValue === this.#watching) return;
|
|
166
|
+
if (this.#watching) this.#stopWatching();
|
|
167
|
+
else this.#watchChildren();
|
|
168
|
+
}
|
|
169
|
+
#watchChildren() {
|
|
170
|
+
this.#watching = true;
|
|
171
|
+
for (const child of this.element.children) {
|
|
172
|
+
const owner = hookOwners.get(child);
|
|
173
|
+
if (owner === void 0 || !owner.pending()) this.#clearArrivedHook(child);
|
|
174
|
+
}
|
|
175
|
+
if (typeof MutationObserver !== "undefined") {
|
|
176
|
+
this.#observer = new MutationObserver((mutations) => this.#onMutations(mutations));
|
|
177
|
+
this.#observer.observe(this.element, { childList: true });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
#stopWatching() {
|
|
181
|
+
this.#watching = false;
|
|
146
182
|
this.#observer?.disconnect();
|
|
147
183
|
this.#observer = null;
|
|
148
|
-
this.#removal.clearAll();
|
|
149
184
|
}
|
|
150
|
-
/** Drops a hook that arrived with the DOM, along with this connection's claim on it. */
|
|
151
185
|
#clearArrivedHook(el) {
|
|
152
|
-
if (hookOwners.get(el) === this) hookOwners.delete(el);
|
|
186
|
+
if (hookOwners.get(el)?.owner === this) hookOwners.delete(el);
|
|
153
187
|
TRANSIENT.reset(el);
|
|
154
188
|
}
|
|
155
|
-
/** Highlights every element child added by a childList mutation. */
|
|
156
189
|
#onMutations(mutations) {
|
|
157
190
|
for (const mutation of mutations) {
|
|
158
191
|
for (const node of mutation.addedNodes) {
|
|
@@ -160,11 +193,6 @@ var HighlightController = class extends Controller {
|
|
|
160
193
|
}
|
|
161
194
|
}
|
|
162
195
|
}
|
|
163
|
-
/**
|
|
164
|
-
* Flags `el` with `data-highlight` and schedules its removal (unless reduced-motion).
|
|
165
|
-
*
|
|
166
|
-
* @stimeoRuntimeOnly `duration` is the length of the one emphasis this call arms.
|
|
167
|
-
*/
|
|
168
196
|
#highlight(el) {
|
|
169
197
|
if (prefersReducedMotion()) return;
|
|
170
198
|
this.#releasePending(el);
|
|
@@ -177,27 +205,31 @@ var HighlightController = class extends Controller {
|
|
|
177
205
|
el.removeAttribute("data-highlight");
|
|
178
206
|
this.dispatch("end", { target: el, detail: { element: el } });
|
|
179
207
|
},
|
|
180
|
-
this
|
|
208
|
+
this.#safeDuration
|
|
181
209
|
);
|
|
182
|
-
hookOwners.set(el,
|
|
210
|
+
hookOwners.set(el, {
|
|
211
|
+
owner: this,
|
|
212
|
+
pending: () => this.#removal.has(el),
|
|
213
|
+
cancel: () => this.#cancelPending(el)
|
|
214
|
+
});
|
|
183
215
|
}
|
|
184
|
-
/**
|
|
185
|
-
* Releases whichever removal timer holds `el`'s hook. The row may have been
|
|
186
|
-
* highlighted inside a different watched container before it moved here, and that
|
|
187
|
-
* container's timer is reachable only through the shared owner registry.
|
|
188
|
-
*/
|
|
189
216
|
#releasePending(el) {
|
|
190
217
|
const owner = hookOwners.get(el);
|
|
191
|
-
if (owner !== void 0 && owner !== this) owner
|
|
192
|
-
this.#cancelPending(el);
|
|
218
|
+
if (owner !== void 0 && owner.owner !== this) owner.cancel();
|
|
193
219
|
}
|
|
194
|
-
/** Releases `el`'s pending removal timer, if it has one, and this connection's claim. */
|
|
195
220
|
#cancelPending(el) {
|
|
196
221
|
this.#removal.clear(el);
|
|
197
|
-
|
|
222
|
+
}
|
|
223
|
+
get #safeDuration() {
|
|
224
|
+
return this.#numbers.read(
|
|
225
|
+
this,
|
|
226
|
+
"duration",
|
|
227
|
+
this.durationValue,
|
|
228
|
+
_HighlightController.values.duration.default,
|
|
229
|
+
_HighlightController.valueConstraints.duration
|
|
230
|
+
);
|
|
198
231
|
}
|
|
199
232
|
};
|
|
200
233
|
|
|
201
234
|
export { HighlightController };
|
|
202
|
-
//# sourceMappingURL=highlight_controller.js.map
|
|
203
235
|
//# sourceMappingURL=highlight_controller.js.map
|