@rettangoli/ui 1.2.2 → 1.2.4

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rettangoli/ui",
3
- "version": "1.2.2",
3
+ "version": "1.2.4",
4
4
  "description": "A UI component library for building web interfaces.",
5
5
  "main": "dist/rettangoli-esm.min.js",
6
6
  "type": "module",
@@ -106,12 +106,19 @@ class RettangoliDialogElement extends HTMLElement {
106
106
  this._adaptiveFrameId = null;
107
107
  this._layoutRetryCount = 0;
108
108
  this._observedContentElement = null;
109
+ this._managedLongTokenTextElements = new Set();
110
+ this._contentMutationObserver = typeof MutationObserver !== "undefined"
111
+ ? new MutationObserver(() => {
112
+ this._syncLongTokenWrapping();
113
+ })
114
+ : null;
109
115
  this._resizeObserver = typeof ResizeObserver !== "undefined"
110
116
  ? new ResizeObserver(() => {
111
117
  this._scheduleAdaptiveCentering();
112
118
  })
113
119
  : null;
114
120
  this._onSlotChange = () => {
121
+ this._syncLongTokenWrapping();
115
122
  this._observeAssignedContent();
116
123
  this._scheduleAdaptiveCentering({ resetRetries: true });
117
124
  };
@@ -175,6 +182,7 @@ class RettangoliDialogElement extends HTMLElement {
175
182
 
176
183
  disconnectedCallback() {
177
184
  this._isConnected = false;
185
+ this._clearManagedLongTokenWrapping();
178
186
  this._stopAdaptiveObservers();
179
187
  if (this._slotElement) {
180
188
  this._slotElement.removeEventListener('slotchange', this._onSlotChange);
@@ -211,6 +219,58 @@ class RettangoliDialogElement extends HTMLElement {
211
219
  }
212
220
  }
213
221
 
222
+ _clearManagedLongTokenWrapping() {
223
+ for (const textElement of this._managedLongTokenTextElements) {
224
+ if (textElement?.isConnected) {
225
+ textElement.removeAttribute("break-long-tokens");
226
+ }
227
+ }
228
+ this._managedLongTokenTextElements.clear();
229
+ }
230
+
231
+ _collectTextElements(node, collected) {
232
+ if (!node || node.nodeType !== Node.ELEMENT_NODE) {
233
+ return;
234
+ }
235
+
236
+ if (node.localName === "rtgl-text") {
237
+ collected.push(node);
238
+ }
239
+
240
+ for (const child of node.children) {
241
+ this._collectTextElements(child, collected);
242
+ }
243
+
244
+ if (node.shadowRoot) {
245
+ for (const child of node.shadowRoot.children) {
246
+ this._collectTextElements(child, collected);
247
+ }
248
+ }
249
+ }
250
+
251
+ _syncLongTokenWrapping() {
252
+ this._clearManagedLongTokenWrapping();
253
+
254
+ if (!this._slotElement) {
255
+ return;
256
+ }
257
+
258
+ const assignedNodes = this._slotElement.assignedNodes({ flatten: true });
259
+ const textElements = [];
260
+
261
+ for (const node of assignedNodes) {
262
+ this._collectTextElements(node, textElements);
263
+ }
264
+
265
+ for (const textElement of textElements) {
266
+ if (textElement.hasAttribute("ellipsis") || textElement.hasAttribute("break-long-tokens")) {
267
+ continue;
268
+ }
269
+ textElement.setAttribute("break-long-tokens", "");
270
+ this._managedLongTokenTextElements.add(textElement);
271
+ }
272
+ }
273
+
214
274
  // Internal methods
215
275
  _showModal() {
216
276
  if (!this._dialogElement.open) {
@@ -228,6 +288,7 @@ class RettangoliDialogElement extends HTMLElement {
228
288
  this._dialogElement.scrollTop = 0;
229
289
 
230
290
  window.addEventListener("resize", this._onWindowResize);
291
+ this._syncLongTokenWrapping();
231
292
  this._observeAssignedContent();
232
293
  this._layoutRetryCount = 0;
233
294
  // Apply the first centering pass before paint so the enter animation
@@ -238,6 +299,7 @@ class RettangoliDialogElement extends HTMLElement {
238
299
 
239
300
  _hideModal() {
240
301
  if (this._dialogElement.open) {
302
+ this._clearManagedLongTokenWrapping();
241
303
  this._stopAdaptiveObservers();
242
304
  this._dialogElement.close();
243
305
 
@@ -269,6 +331,9 @@ class RettangoliDialogElement extends HTMLElement {
269
331
  if (this._resizeObserver && this._observedContentElement) {
270
332
  this._resizeObserver.unobserve(this._observedContentElement);
271
333
  }
334
+ if (this._contentMutationObserver) {
335
+ this._contentMutationObserver.disconnect();
336
+ }
272
337
  this._observedContentElement = null;
273
338
  }
274
339
 
@@ -281,7 +346,7 @@ class RettangoliDialogElement extends HTMLElement {
281
346
  }
282
347
 
283
348
  _observeAssignedContent() {
284
- if (!this._resizeObserver) {
349
+ if (!this._resizeObserver && !this._contentMutationObserver) {
285
350
  return;
286
351
  }
287
352
  const nextContentElement = this._getAssignedContentElement();
@@ -289,11 +354,25 @@ class RettangoliDialogElement extends HTMLElement {
289
354
  return;
290
355
  }
291
356
  if (this._observedContentElement) {
292
- this._resizeObserver.unobserve(this._observedContentElement);
357
+ if (this._resizeObserver) {
358
+ this._resizeObserver.unobserve(this._observedContentElement);
359
+ }
360
+ if (this._contentMutationObserver) {
361
+ this._contentMutationObserver.disconnect();
362
+ }
293
363
  }
294
364
  this._observedContentElement = nextContentElement;
295
365
  if (this._observedContentElement) {
296
- this._resizeObserver.observe(this._observedContentElement);
366
+ if (this._resizeObserver) {
367
+ this._resizeObserver.observe(this._observedContentElement);
368
+ }
369
+ if (this._contentMutationObserver) {
370
+ this._contentMutationObserver.observe(this._observedContentElement, {
371
+ childList: true,
372
+ subtree: true,
373
+ });
374
+ }
375
+ this._syncLongTokenWrapping();
297
376
  }
298
377
  }
299
378
 
@@ -199,8 +199,8 @@ class RettangoliPopoverElement extends HTMLElement {
199
199
  this._contentWrapper.setAttribute("bw", "xs");
200
200
  this._contentWrapper.setAttribute("bc", "bo");
201
201
  this._contentWrapper.setAttribute("br", "md");
202
- this._contentWrapper.setAttribute("ph", "md");
203
- this._contentWrapper.setAttribute("pv", "md");
202
+ this._contentWrapper.setAttribute("ph", "sm");
203
+ this._contentWrapper.setAttribute("pv", "sm");
204
204
  this._contentWrapper.setAttribute("style", DEFAULT_CONTENT_STYLE);
205
205
  }
206
206
 
@@ -232,8 +232,8 @@ class RettangoliPopoverElement extends HTMLElement {
232
232
  }
233
233
 
234
234
  wrapper.setAttribute("bgc", this.getAttribute("content-bgc") || "bg");
235
- wrapper.setAttribute("ph", "md");
236
- wrapper.setAttribute("pv", this.getAttribute("content-pv") || "md");
235
+ wrapper.setAttribute("ph", "sm");
236
+ wrapper.setAttribute("pv", this.getAttribute("content-pv") || "sm");
237
237
 
238
238
  const contentStyle = this.getAttribute("content-style");
239
239
  wrapper.setAttribute("style", contentStyle ? `${DEFAULT_CONTENT_STYLE} ${contentStyle}` : DEFAULT_CONTENT_STYLE);
@@ -58,7 +58,7 @@ class RettangoliTextElement extends HTMLElement {
58
58
  }
59
59
 
60
60
  static get observedAttributes() {
61
- return ["key", "w", "ellipsis", "href", "new-tab", "rel"];
61
+ return ["key", "w", "ellipsis", "href", "new-tab", "rel", "break-long-tokens"];
62
62
  }
63
63
 
64
64
  connectedCallback() {
@@ -77,15 +77,20 @@ class RettangoliTextElement extends HTMLElement {
77
77
  _updateStyling() {
78
78
  const width = dimensionWithUnit(this.getAttribute("w"));
79
79
  const ellipsis = this.hasAttribute("ellipsis");
80
+ const breakLongTokens = this.hasAttribute("break-long-tokens");
80
81
 
81
82
  if (ellipsis) {
82
83
  this.style.overflow = "hidden";
83
84
  this.style.textOverflow = "ellipsis";
84
85
  this.style.whiteSpace = "nowrap";
86
+ this.style.overflowWrap = "";
87
+ this.style.wordBreak = "";
85
88
  } else {
86
89
  this.style.overflow = "";
87
90
  this.style.textOverflow = "";
88
91
  this.style.whiteSpace = "";
92
+ this.style.overflowWrap = breakLongTokens ? "anywhere" : "";
93
+ this.style.wordBreak = breakLongTokens ? "break-word" : "";
89
94
  }
90
95
 
91
96
  // Allow shrinking in flex layouts so ellipsis and wrapping constraints work predictably.