@rio-cloud/rio-uikit 1.13.1 → 1.13.2

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/.DS_Store CHANGED
Binary file
@@ -2,6 +2,7 @@ import React, { type ForwardRefExoticComponent, type HTMLProps, type PropsWithCh
2
2
  import type { ObjectValues } from '../../utils/ObjectValues';
3
3
  export declare const STYLES_MAP: {
4
4
  readonly DEFAULT: "default";
5
+ readonly UNSTYLED: "unstyled";
5
6
  readonly PRIMARY: "primary";
6
7
  readonly SECONDARY: "secondary";
7
8
  readonly INFO: "info";
@@ -125,6 +126,7 @@ export type ButtonProps = Omit<HTMLProps<HTMLButtonElement>, 'type' | 'onClick'>
125
126
  type Props = PropsWithChildren<ButtonProps>;
126
127
  type ButtonType = ForwardRefExoticComponent<Props & RefAttributes<HTMLButtonElement>> & {
127
128
  DEFAULT: 'default';
129
+ UNSTYLED: 'unstyled';
128
130
  PRIMARY: 'primary';
129
131
  SECONDARY: 'secondary';
130
132
  INFO: 'info';
@@ -6,6 +6,7 @@ import { createButtonRipple } from '../../utils/buttonEffect';
6
6
  import useMergeRefs from '../../hooks/useMergeRefs';
7
7
  export const STYLES_MAP = {
8
8
  DEFAULT: 'default',
9
+ UNSTYLED: 'unstyled',
9
10
  PRIMARY: 'primary',
10
11
  SECONDARY: 'secondary',
11
12
  INFO: 'info',
@@ -2,6 +2,7 @@ import React, { type ForwardRefExoticComponent, type HTMLProps, type PropsWithCh
2
2
  import type { ObjectValues } from '../../utils/ObjectValues';
3
3
  export declare const STYLES_MAP: {
4
4
  readonly DEFAULT: "default";
5
+ readonly UNSTYLED: "unstyled";
5
6
  readonly PRIMARY: "primary";
6
7
  readonly SECONDARY: "secondary";
7
8
  readonly INFO: "info";
@@ -125,6 +126,7 @@ export type ButtonProps = Omit<HTMLProps<HTMLButtonElement>, 'type' | 'onClick'>
125
126
  type Props = PropsWithChildren<ButtonProps>;
126
127
  type ButtonType = ForwardRefExoticComponent<Props & RefAttributes<HTMLButtonElement>> & {
127
128
  DEFAULT: 'default';
129
+ UNSTYLED: 'unstyled';
128
130
  PRIMARY: 'primary';
129
131
  SECONDARY: 'secondary';
130
132
  INFO: 'info';
@@ -10,6 +10,7 @@ const buttonEffect_1 = require("../../utils/buttonEffect");
10
10
  const useMergeRefs_1 = tslib_1.__importDefault(require("../../hooks/useMergeRefs"));
11
11
  exports.STYLES_MAP = {
12
12
  DEFAULT: 'default',
13
+ UNSTYLED: 'unstyled',
13
14
  PRIMARY: 'primary',
14
15
  SECONDARY: 'secondary',
15
16
  INFO: 'info',
@@ -30,6 +30,9 @@
30
30
  */
31
31
  Object.defineProperty(exports, "__esModule", { value: true });
32
32
  exports.hidePiiData = exports.shufflePii = exports.shuffleText = void 0;
33
+ const ATTR_DATA_PII = 'data-pii';
34
+ const ATTR_ORIGINAL_PII = 'data-original-pii';
35
+ const ATTR_OBFUSCATED_PII = 'data-obfuscated-pii';
33
36
  /**
34
37
  * In place Fisher Yates shuffle.
35
38
  * Randomizes the order of the given array using `Math.random()`.
@@ -306,26 +309,26 @@ const hidePiiData = (target, forceResult) => {
306
309
  const elements = target instanceof Element ? [target] : Array.from(target);
307
310
  for (const el of elements) {
308
311
  // Mark the element as processed so other parts of the app can detect its state
309
- el.setAttribute('data-pii', 'hidden');
312
+ el.setAttribute(ATTR_DATA_PII, 'hidden');
310
313
  const beforeText = (el.textContent || '').trim();
311
314
  // If the selected element is an <input>, shuffle its value instead of text nodes
312
315
  if (el.matches?.('input') || el.tagName === 'INPUT') {
313
316
  const input = el;
314
317
  const val = input.value || '';
315
318
  if (typeof forceResult === 'string' && forceResult.length > 0) {
316
- el.setAttribute('data-original-pii', val);
319
+ el.setAttribute(ATTR_ORIGINAL_PII, val);
317
320
  input.value = forceResult;
318
- el.setAttribute('data-obfuscated-pii', input.value);
321
+ el.setAttribute(ATTR_OBFUSCATED_PII, input.value);
319
322
  continue;
320
323
  }
321
- el.setAttribute('data-original-pii', val);
324
+ el.setAttribute(ATTR_ORIGINAL_PII, val);
322
325
  const trimmed = val.trim();
323
326
  if (trimmed.length > 0) {
324
327
  const shuffled = (0, exports.shufflePii)(val);
325
328
  if (shuffled !== val) {
326
329
  input.value = shuffled;
327
330
  }
328
- el.setAttribute('data-obfuscated-pii', input.value);
331
+ el.setAttribute(ATTR_OBFUSCATED_PII, input.value);
329
332
  }
330
333
  continue; // skip text-node processing for inputs
331
334
  }
@@ -365,10 +368,10 @@ const hidePiiData = (target, forceResult) => {
365
368
  };
366
369
  if (typeof forceResult === 'string' && forceResult.length > 0) {
367
370
  if (beforeText) {
368
- el.setAttribute('data-original-pii', beforeText);
371
+ el.setAttribute(ATTR_ORIGINAL_PII, beforeText);
369
372
  }
370
373
  applyForcedText(el, forceResult);
371
- el.setAttribute('data-obfuscated-pii', (el.textContent || '').trim());
374
+ el.setAttribute(ATTR_OBFUSCATED_PII, (el.textContent || '').trim());
372
375
  continue;
373
376
  }
374
377
  let anyTextChanged = false;
@@ -377,20 +380,39 @@ const hidePiiData = (target, forceResult) => {
377
380
  let node = walker.nextNode();
378
381
  while (node) {
379
382
  const txtNode = node;
380
- const original = txtNode.nodeValue || '';
381
- const trimmed = original.trim();
383
+ const original = String(txtNode.textContent || '');
384
+ // Whitespace fix 1/2: If the text node contains only whitespace, remove it entirely
385
+ if (/^\s*$/.test(original)) {
386
+ const nextNode = walker.nextNode();
387
+ txtNode.remove();
388
+ node = nextNode;
389
+ continue;
390
+ }
391
+ // Normalize all whitespace in non-empty text nodes to a single space
392
+ const normalized = original.replace(/\s+/g, ' ');
393
+ const trimmed = normalized.trim();
382
394
  if (trimmed.length > 0) {
383
- const shuffled = (0, exports.shufflePii)(original);
384
- if (shuffled !== original) {
385
- txtNode.nodeValue = shuffled;
395
+ const shuffled = (0, exports.shufflePii)(normalized);
396
+ if (shuffled !== normalized) {
397
+ txtNode.textContent = shuffled;
386
398
  anyTextChanged = true;
387
399
  }
388
400
  }
389
401
  node = walker.nextNode();
390
402
  }
403
+ // Whitespace fix 2/2: Restore spacing between adjacent text nodes
404
+ const directTextNodes = Array.from(el.childNodes).filter(n => n.nodeType === Node.TEXT_NODE);
405
+ for (let i = 0; i < directTextNodes.length - 1; i++) {
406
+ const current = directTextNodes[i];
407
+ const next = directTextNodes[i + 1];
408
+ if (current.textContent?.trim() && next.textContent?.trim()) {
409
+ const spacer = document.createTextNode(' ');
410
+ current.parentNode?.insertBefore(spacer, next);
411
+ }
412
+ }
391
413
  const currentText = (el.textContent || '').trim();
392
414
  if (anyTextChanged && currentText) {
393
- el.setAttribute('data-obfuscated-pii', currentText);
415
+ el.setAttribute(ATTR_OBFUSCATED_PII, currentText);
394
416
  if (beforeText) {
395
417
  el.setAttribute('data-original-pii', beforeText);
396
418
  }
@@ -108,7 +108,7 @@ const initPiiObserver = () => {
108
108
  ensureHiddenConsistent(node);
109
109
  const descendants = node.querySelectorAll(SELECTOR_PII_OBFUSCATED + SELECTOR_PII_ORIGINAL);
110
110
  for (const descendant of descendants) {
111
- console.log('data-original-pii:', descendant.getAttribute(ATTR_ORIGINAL_PII));
111
+ // console.log('data-original-pii:', descendant.getAttribute(ATTR_ORIGINAL_PII));
112
112
  ensureHiddenConsistent(descendant);
113
113
  }
114
114
  }
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.13.1"
2
+ "version": "1.13.2"
3
3
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rio-cloud/rio-uikit",
3
- "version": "1.13.1",
3
+ "version": "1.13.2",
4
4
  "description": "The RIO UIKIT component library",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,6 +27,9 @@
27
27
  * - `data-pii="hidden"` is written to elements that have already been processed to help external code introspect state.
28
28
  * - `data-hide-pii="shuffle"` on `<html>` is used by an external observer to decide when to call `hidePiiData`.
29
29
  */
30
+ const ATTR_DATA_PII = 'data-pii';
31
+ const ATTR_ORIGINAL_PII = 'data-original-pii';
32
+ const ATTR_OBFUSCATED_PII = 'data-obfuscated-pii';
30
33
  /**
31
34
  * In place Fisher Yates shuffle.
32
35
  * Randomizes the order of the given array using `Math.random()`.
@@ -301,26 +304,26 @@ export const hidePiiData = (target, forceResult) => {
301
304
  const elements = target instanceof Element ? [target] : Array.from(target);
302
305
  for (const el of elements) {
303
306
  // Mark the element as processed so other parts of the app can detect its state
304
- el.setAttribute('data-pii', 'hidden');
307
+ el.setAttribute(ATTR_DATA_PII, 'hidden');
305
308
  const beforeText = (el.textContent || '').trim();
306
309
  // If the selected element is an <input>, shuffle its value instead of text nodes
307
310
  if (el.matches?.('input') || el.tagName === 'INPUT') {
308
311
  const input = el;
309
312
  const val = input.value || '';
310
313
  if (typeof forceResult === 'string' && forceResult.length > 0) {
311
- el.setAttribute('data-original-pii', val);
314
+ el.setAttribute(ATTR_ORIGINAL_PII, val);
312
315
  input.value = forceResult;
313
- el.setAttribute('data-obfuscated-pii', input.value);
316
+ el.setAttribute(ATTR_OBFUSCATED_PII, input.value);
314
317
  continue;
315
318
  }
316
- el.setAttribute('data-original-pii', val);
319
+ el.setAttribute(ATTR_ORIGINAL_PII, val);
317
320
  const trimmed = val.trim();
318
321
  if (trimmed.length > 0) {
319
322
  const shuffled = shufflePii(val);
320
323
  if (shuffled !== val) {
321
324
  input.value = shuffled;
322
325
  }
323
- el.setAttribute('data-obfuscated-pii', input.value);
326
+ el.setAttribute(ATTR_OBFUSCATED_PII, input.value);
324
327
  }
325
328
  continue; // skip text-node processing for inputs
326
329
  }
@@ -360,10 +363,10 @@ export const hidePiiData = (target, forceResult) => {
360
363
  };
361
364
  if (typeof forceResult === 'string' && forceResult.length > 0) {
362
365
  if (beforeText) {
363
- el.setAttribute('data-original-pii', beforeText);
366
+ el.setAttribute(ATTR_ORIGINAL_PII, beforeText);
364
367
  }
365
368
  applyForcedText(el, forceResult);
366
- el.setAttribute('data-obfuscated-pii', (el.textContent || '').trim());
369
+ el.setAttribute(ATTR_OBFUSCATED_PII, (el.textContent || '').trim());
367
370
  continue;
368
371
  }
369
372
  let anyTextChanged = false;
@@ -372,20 +375,39 @@ export const hidePiiData = (target, forceResult) => {
372
375
  let node = walker.nextNode();
373
376
  while (node) {
374
377
  const txtNode = node;
375
- const original = txtNode.nodeValue || '';
376
- const trimmed = original.trim();
378
+ const original = String(txtNode.textContent || '');
379
+ // Whitespace fix 1/2: If the text node contains only whitespace, remove it entirely
380
+ if (/^\s*$/.test(original)) {
381
+ const nextNode = walker.nextNode();
382
+ txtNode.remove();
383
+ node = nextNode;
384
+ continue;
385
+ }
386
+ // Normalize all whitespace in non-empty text nodes to a single space
387
+ const normalized = original.replace(/\s+/g, ' ');
388
+ const trimmed = normalized.trim();
377
389
  if (trimmed.length > 0) {
378
- const shuffled = shufflePii(original);
379
- if (shuffled !== original) {
380
- txtNode.nodeValue = shuffled;
390
+ const shuffled = shufflePii(normalized);
391
+ if (shuffled !== normalized) {
392
+ txtNode.textContent = shuffled;
381
393
  anyTextChanged = true;
382
394
  }
383
395
  }
384
396
  node = walker.nextNode();
385
397
  }
398
+ // Whitespace fix 2/2: Restore spacing between adjacent text nodes
399
+ const directTextNodes = Array.from(el.childNodes).filter(n => n.nodeType === Node.TEXT_NODE);
400
+ for (let i = 0; i < directTextNodes.length - 1; i++) {
401
+ const current = directTextNodes[i];
402
+ const next = directTextNodes[i + 1];
403
+ if (current.textContent?.trim() && next.textContent?.trim()) {
404
+ const spacer = document.createTextNode(' ');
405
+ current.parentNode?.insertBefore(spacer, next);
406
+ }
407
+ }
386
408
  const currentText = (el.textContent || '').trim();
387
409
  if (anyTextChanged && currentText) {
388
- el.setAttribute('data-obfuscated-pii', currentText);
410
+ el.setAttribute(ATTR_OBFUSCATED_PII, currentText);
389
411
  if (beforeText) {
390
412
  el.setAttribute('data-original-pii', beforeText);
391
413
  }
@@ -105,7 +105,7 @@ export const initPiiObserver = () => {
105
105
  ensureHiddenConsistent(node);
106
106
  const descendants = node.querySelectorAll(SELECTOR_PII_OBFUSCATED + SELECTOR_PII_ORIGINAL);
107
107
  for (const descendant of descendants) {
108
- console.log('data-original-pii:', descendant.getAttribute(ATTR_ORIGINAL_PII));
108
+ // console.log('data-original-pii:', descendant.getAttribute(ATTR_ORIGINAL_PII));
109
109
  ensureHiddenConsistent(descendant);
110
110
  }
111
111
  }
package/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "1.13.1"
2
+ "version": "1.13.2"
3
3
  }