uiik 1.3.6 → 1.4.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.
package/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * uiik v1.3.6
2
+ * uiik v1.4.0
3
3
  * A UI interactions kit includes draggable, splittable, rotatable, selectable, etc.
4
4
  * https://github.com/holyhigh2/uiik
5
5
  * c) 2021-2025 @holyhigh2 may be freely distributed under the MIT license
@@ -7,11 +7,11 @@
7
7
  import { find, map, toArray, each, reject, includes, some, flatMap, size } from 'myfx/collection';
8
8
  import { isDefined, isNumber, isNaN, isString, isArrayLike, isElement, isEmpty, isBlank, isArray, isFunction, isBoolean, isUndefined } from 'myfx/is';
9
9
  import { get, assign, merge } from 'myfx/object';
10
+ import { isElement as isElement$1, filter, last } from 'myfx';
10
11
  import { compact, findIndex } from 'myfx/array';
11
12
  import { split, test } from 'myfx/string';
12
13
  import { closest } from 'myfx/tree';
13
14
  import { alphaId } from 'myfx/utils';
14
- import { filter, last } from 'myfx';
15
15
 
16
16
  /******************************************************************************
17
17
  Copyright (c) Microsoft Corporation.
@@ -978,13 +978,13 @@ function newSplittable(container, opts) {
978
978
  const CLASS_RESIZABLE_HANDLE = "uii-resizable-handle";
979
979
  const CLASS_RESIZABLE_HANDLE_DIR = "uii-resizable-handle-";
980
980
  const CLASS_RESIZABLE_HANDLE_ACTIVE = "uii-resizable-handle-active";
981
+ const CLASS_RESIZABLE_GHOST = "uii-resizable-ghost";
981
982
  const EXP_DIR = new RegExp(CLASS_RESIZABLE_HANDLE_DIR + "(?<dir>[nesw]+)");
982
983
  class Resizable extends Uii {
983
984
  constructor(els, opts) {
984
985
  super(els, assign({
985
986
  handleSize: 8,
986
987
  minSize: 50,
987
- dir: ["n", "s", "e", "w", "ne", "nw", "se", "sw"],
988
988
  ghost: false,
989
989
  offset: 0,
990
990
  }, opts));
@@ -1111,11 +1111,9 @@ class Resizable extends Uii {
1111
1111
  }
1112
1112
  if (ghostNode) {
1113
1113
  if (ghostClass) {
1114
- ghostNode.className =
1115
- ghostNode.className.replace(ghostClass, "") +
1116
- " " +
1117
- ghostClass;
1114
+ ghostNode.classList.add(ghostClass);
1118
1115
  }
1116
+ ghostNode.classList.toggle(CLASS_RESIZABLE_GHOST, true);
1119
1117
  (_a = panel.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(ghostNode);
1120
1118
  transform = wrapper(ghostNode);
1121
1119
  onClone && onClone({ clone: ghostNode }, ev);
@@ -1177,7 +1175,7 @@ class Resizable extends Uii {
1177
1175
  }
1178
1176
  startPointXy = getPointInContainer(ev, container, offsetParentRect, offsetParentCStyle, matrixInfo);
1179
1177
  onStart &&
1180
- onStart.call(uiik, { w: originW, h: originH, transform }, ev);
1178
+ onStart.call(uiik, { w: originW, h: originH, transform, handle, ghost: ghostNode }, ev);
1181
1179
  });
1182
1180
  onPointerMove((args) => {
1183
1181
  const { ev, offX, offY } = args;
@@ -1398,38 +1396,13 @@ class Resizable extends Uii {
1398
1396
  break;
1399
1397
  }
1400
1398
  if (aspectRatio) {
1401
- if (changeW) {
1402
- style.width = w + "px";
1403
- style.height = w / aspectRatio + "px";
1404
- }
1405
1399
  if (changeH && dir !== "sw") {
1406
1400
  if (dir === "nw") {
1407
1401
  y = originY - w / aspectRatio + originH;
1408
1402
  }
1409
- else {
1410
- style.width = h * aspectRatio + "px";
1411
- style.height = h + "px";
1412
- }
1413
1403
  }
1414
1404
  }
1415
- else {
1416
- if (changeW) {
1417
- resize(transform, style, w);
1418
- }
1419
- if (changeH) {
1420
- resize(transform, style, undefined, h);
1421
- }
1422
- }
1423
- if (changeY) {
1424
- transform.moveTo(x, y + sY);
1425
- }
1426
- if (changeX) {
1427
- transform.moveTo(x + sX, y);
1428
- }
1429
- lastX = x;
1430
- lastY = y;
1431
- currentW = w;
1432
- currentH = h;
1405
+ let canResize = true;
1433
1406
  if (onResize && onResize.call) {
1434
1407
  onResize.call;
1435
1408
  const panelRect = getRectInContainer(panel, panel.parentElement, matrixInfo);
@@ -1437,7 +1410,7 @@ class Resizable extends Uii {
1437
1410
  let centerY = Math.round(panelRect.y + panelRect.h / 2);
1438
1411
  let sx = Math.round(centerX - originW / 2);
1439
1412
  let sy = Math.round(centerY - originH / 2);
1440
- onResize.call(uiik, {
1413
+ canResize = onResize.call(uiik, {
1441
1414
  w,
1442
1415
  h,
1443
1416
  ow: w - originW,
@@ -1449,19 +1422,68 @@ class Resizable extends Uii {
1449
1422
  sy: sy,
1450
1423
  deg: matrixInfo.angle,
1451
1424
  transform,
1425
+ handle
1452
1426
  }, ev);
1453
1427
  }
1428
+ if (canResize !== false) {
1429
+ if (aspectRatio) {
1430
+ if (changeW) {
1431
+ style.width = w + "px";
1432
+ style.height = w / aspectRatio + "px";
1433
+ }
1434
+ if (changeH && dir !== "sw" && dir !== "nw") {
1435
+ style.width = h * aspectRatio + "px";
1436
+ style.height = h + "px";
1437
+ }
1438
+ }
1439
+ else {
1440
+ if (changeW) {
1441
+ resize(transform, style, w);
1442
+ }
1443
+ if (changeH) {
1444
+ resize(transform, style, undefined, h);
1445
+ }
1446
+ }
1447
+ if (changeY) {
1448
+ transform.moveTo(x, y + sY);
1449
+ }
1450
+ if (changeX) {
1451
+ transform.moveTo(x + sX, y);
1452
+ }
1453
+ }
1454
+ lastX = x;
1455
+ lastY = y;
1456
+ currentW = w;
1457
+ currentH = h;
1454
1458
  });
1455
1459
  onPointerEnd((args) => {
1456
1460
  var _a, _b;
1457
1461
  const { ev } = args;
1462
+ let doDefault = true;
1463
+ handle.classList.remove(CLASS_RESIZABLE_HANDLE_ACTIVE);
1464
+ let ghostLeft = '0';
1465
+ let ghostTop = '0';
1466
+ let ghostWidth = '0';
1467
+ let ghostHeight = '0';
1458
1468
  if (ghost && ghostNode) {
1469
+ ghostLeft = ghostNode.style.left;
1470
+ ghostTop = ghostNode.style.top;
1471
+ ghostWidth = ghostNode.style.width;
1472
+ ghostHeight = ghostNode.style.height;
1459
1473
  ((_a = panel.parentNode) === null || _a === void 0 ? void 0 : _a.contains(ghostNode)) &&
1460
1474
  ((_b = panel.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(ghostNode));
1461
- panelStyle.left = ghostNode.style.left;
1462
- panelStyle.top = ghostNode.style.top;
1463
- moveTo(panel, lastX / matrixInfo.scale, lastY / matrixInfo.scale);
1464
- resize(transform, panelStyle, parseFloat(ghostNode.style.width), parseFloat(ghostNode.style.height));
1475
+ }
1476
+ if (onEnd) {
1477
+ doDefault = onEnd.call(uiik, { w: currentW, h: currentH, transform, handle, ghost: ghostNode }, ev);
1478
+ }
1479
+ if (doDefault === false)
1480
+ return;
1481
+ if (ghost && ghostNode) {
1482
+ panelStyle.left = ghostLeft;
1483
+ panelStyle.top = ghostTop;
1484
+ transform = wrapper(panel);
1485
+ transform.moveTo((lastX + sX), (lastY + sY));
1486
+ resize(transform, panelStyle, parseFloat(ghostWidth), parseFloat(ghostHeight));
1465
1487
  }
1466
1488
  if (setOrigin)
1467
1489
  panel.style.transformOrigin = originalTransformOrigin;
@@ -1482,9 +1504,6 @@ class Resizable extends Uii {
1482
1504
  }
1483
1505
  }
1484
1506
  }
1485
- handle.classList.remove(CLASS_RESIZABLE_HANDLE_ACTIVE);
1486
- onEnd &&
1487
- onEnd.call(uiik, { w: currentW, h: currentH, transform }, ev);
1488
1507
  });
1489
1508
  }, {
1490
1509
  threshold: THRESHOLD,
@@ -1501,8 +1520,17 @@ class Resizable extends Uii {
1501
1520
  else if (isFunction(handleStr)) {
1502
1521
  handles = handleStr(panel);
1503
1522
  }
1523
+ else if (isElement$1(handleStr)) {
1524
+ handles = [handleStr];
1525
+ }
1526
+ else if (isArrayLike(handleStr)) {
1527
+ let eles = filter(handleStr, h => isElement$1(h));
1528
+ if (eles.length > 0) {
1529
+ handles = eles;
1530
+ }
1531
+ }
1504
1532
  if (!handles) {
1505
- console.error('Can not find handles with "' + panel.outerHTML + '"');
1533
+ console.error('Can not find handles in "' + panel.outerHTML + '"');
1506
1534
  return;
1507
1535
  }
1508
1536
  handles = isArrayLike(handles) ? handles : [handles];
@@ -2972,7 +3000,7 @@ function newSortable(container, opts) {
2972
3000
  return new Sortable(container, opts);
2973
3001
  }
2974
3002
 
2975
- var version = "1.3.6";
3003
+ var version = "1.4.0";
2976
3004
  var repository = {
2977
3005
  type: "git",
2978
3006
  url: "https://github.com/holyhigh2/uiik"
package/index.js CHANGED
@@ -1,14 +1,14 @@
1
1
  /**
2
- * uiik v1.3.6
2
+ * uiik v1.4.0
3
3
  * A UI interactions kit includes draggable, splittable, rotatable, selectable, etc.
4
4
  * https://github.com/holyhigh2/uiik
5
5
  * c) 2021-2025 @holyhigh2 may be freely distributed under the MIT license
6
6
  */
7
7
  (function (global, factory) {
8
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('myfx/collection'), require('myfx/is'), require('myfx/object'), require('myfx/array'), require('myfx/string'), require('myfx/tree'), require('myfx/utils'), require('myfx')) :
9
- typeof define === 'function' && define.amd ? define(['exports', 'myfx/collection', 'myfx/is', 'myfx/object', 'myfx/array', 'myfx/string', 'myfx/tree', 'myfx/utils', 'myfx'], factory) :
10
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.uiik = {}, global.collection, global.is, global.object, global.array, global.string, global.tree, global.utils, global.myfx));
11
- })(this, (function (exports, collection, is, object, array, string, tree, utils, myfx) { 'use strict';
8
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('myfx/collection'), require('myfx/is'), require('myfx/object'), require('myfx'), require('myfx/array'), require('myfx/string'), require('myfx/tree'), require('myfx/utils')) :
9
+ typeof define === 'function' && define.amd ? define(['exports', 'myfx/collection', 'myfx/is', 'myfx/object', 'myfx', 'myfx/array', 'myfx/string', 'myfx/tree', 'myfx/utils'], factory) :
10
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.uiik = {}, global.collection, global.is, global.object, global.myfx, global.array, global.string, global.tree, global.utils));
11
+ })(this, (function (exports, collection, is, object, myfx, array, string, tree, utils) { 'use strict';
12
12
 
13
13
  /******************************************************************************
14
14
  Copyright (c) Microsoft Corporation.
@@ -975,13 +975,13 @@
975
975
  const CLASS_RESIZABLE_HANDLE = "uii-resizable-handle";
976
976
  const CLASS_RESIZABLE_HANDLE_DIR = "uii-resizable-handle-";
977
977
  const CLASS_RESIZABLE_HANDLE_ACTIVE = "uii-resizable-handle-active";
978
+ const CLASS_RESIZABLE_GHOST = "uii-resizable-ghost";
978
979
  const EXP_DIR = new RegExp(CLASS_RESIZABLE_HANDLE_DIR + "(?<dir>[nesw]+)");
979
980
  class Resizable extends Uii {
980
981
  constructor(els, opts) {
981
982
  super(els, object.assign({
982
983
  handleSize: 8,
983
984
  minSize: 50,
984
- dir: ["n", "s", "e", "w", "ne", "nw", "se", "sw"],
985
985
  ghost: false,
986
986
  offset: 0,
987
987
  }, opts));
@@ -1108,11 +1108,9 @@
1108
1108
  }
1109
1109
  if (ghostNode) {
1110
1110
  if (ghostClass) {
1111
- ghostNode.className =
1112
- ghostNode.className.replace(ghostClass, "") +
1113
- " " +
1114
- ghostClass;
1111
+ ghostNode.classList.add(ghostClass);
1115
1112
  }
1113
+ ghostNode.classList.toggle(CLASS_RESIZABLE_GHOST, true);
1116
1114
  (_a = panel.parentNode) === null || _a === void 0 ? void 0 : _a.appendChild(ghostNode);
1117
1115
  transform = wrapper(ghostNode);
1118
1116
  onClone && onClone({ clone: ghostNode }, ev);
@@ -1174,7 +1172,7 @@
1174
1172
  }
1175
1173
  startPointXy = getPointInContainer(ev, container, offsetParentRect, offsetParentCStyle, matrixInfo);
1176
1174
  onStart &&
1177
- onStart.call(uiik, { w: originW, h: originH, transform }, ev);
1175
+ onStart.call(uiik, { w: originW, h: originH, transform, handle, ghost: ghostNode }, ev);
1178
1176
  });
1179
1177
  onPointerMove((args) => {
1180
1178
  const { ev, offX, offY } = args;
@@ -1395,38 +1393,13 @@
1395
1393
  break;
1396
1394
  }
1397
1395
  if (aspectRatio) {
1398
- if (changeW) {
1399
- style.width = w + "px";
1400
- style.height = w / aspectRatio + "px";
1401
- }
1402
1396
  if (changeH && dir !== "sw") {
1403
1397
  if (dir === "nw") {
1404
1398
  y = originY - w / aspectRatio + originH;
1405
1399
  }
1406
- else {
1407
- style.width = h * aspectRatio + "px";
1408
- style.height = h + "px";
1409
- }
1410
1400
  }
1411
1401
  }
1412
- else {
1413
- if (changeW) {
1414
- resize(transform, style, w);
1415
- }
1416
- if (changeH) {
1417
- resize(transform, style, undefined, h);
1418
- }
1419
- }
1420
- if (changeY) {
1421
- transform.moveTo(x, y + sY);
1422
- }
1423
- if (changeX) {
1424
- transform.moveTo(x + sX, y);
1425
- }
1426
- lastX = x;
1427
- lastY = y;
1428
- currentW = w;
1429
- currentH = h;
1402
+ let canResize = true;
1430
1403
  if (onResize && onResize.call) {
1431
1404
  onResize.call;
1432
1405
  const panelRect = getRectInContainer(panel, panel.parentElement, matrixInfo);
@@ -1434,7 +1407,7 @@
1434
1407
  let centerY = Math.round(panelRect.y + panelRect.h / 2);
1435
1408
  let sx = Math.round(centerX - originW / 2);
1436
1409
  let sy = Math.round(centerY - originH / 2);
1437
- onResize.call(uiik, {
1410
+ canResize = onResize.call(uiik, {
1438
1411
  w,
1439
1412
  h,
1440
1413
  ow: w - originW,
@@ -1446,19 +1419,68 @@
1446
1419
  sy: sy,
1447
1420
  deg: matrixInfo.angle,
1448
1421
  transform,
1422
+ handle
1449
1423
  }, ev);
1450
1424
  }
1425
+ if (canResize !== false) {
1426
+ if (aspectRatio) {
1427
+ if (changeW) {
1428
+ style.width = w + "px";
1429
+ style.height = w / aspectRatio + "px";
1430
+ }
1431
+ if (changeH && dir !== "sw" && dir !== "nw") {
1432
+ style.width = h * aspectRatio + "px";
1433
+ style.height = h + "px";
1434
+ }
1435
+ }
1436
+ else {
1437
+ if (changeW) {
1438
+ resize(transform, style, w);
1439
+ }
1440
+ if (changeH) {
1441
+ resize(transform, style, undefined, h);
1442
+ }
1443
+ }
1444
+ if (changeY) {
1445
+ transform.moveTo(x, y + sY);
1446
+ }
1447
+ if (changeX) {
1448
+ transform.moveTo(x + sX, y);
1449
+ }
1450
+ }
1451
+ lastX = x;
1452
+ lastY = y;
1453
+ currentW = w;
1454
+ currentH = h;
1451
1455
  });
1452
1456
  onPointerEnd((args) => {
1453
1457
  var _a, _b;
1454
1458
  const { ev } = args;
1459
+ let doDefault = true;
1460
+ handle.classList.remove(CLASS_RESIZABLE_HANDLE_ACTIVE);
1461
+ let ghostLeft = '0';
1462
+ let ghostTop = '0';
1463
+ let ghostWidth = '0';
1464
+ let ghostHeight = '0';
1455
1465
  if (ghost && ghostNode) {
1466
+ ghostLeft = ghostNode.style.left;
1467
+ ghostTop = ghostNode.style.top;
1468
+ ghostWidth = ghostNode.style.width;
1469
+ ghostHeight = ghostNode.style.height;
1456
1470
  ((_a = panel.parentNode) === null || _a === void 0 ? void 0 : _a.contains(ghostNode)) &&
1457
1471
  ((_b = panel.parentNode) === null || _b === void 0 ? void 0 : _b.removeChild(ghostNode));
1458
- panelStyle.left = ghostNode.style.left;
1459
- panelStyle.top = ghostNode.style.top;
1460
- moveTo(panel, lastX / matrixInfo.scale, lastY / matrixInfo.scale);
1461
- resize(transform, panelStyle, parseFloat(ghostNode.style.width), parseFloat(ghostNode.style.height));
1472
+ }
1473
+ if (onEnd) {
1474
+ doDefault = onEnd.call(uiik, { w: currentW, h: currentH, transform, handle, ghost: ghostNode }, ev);
1475
+ }
1476
+ if (doDefault === false)
1477
+ return;
1478
+ if (ghost && ghostNode) {
1479
+ panelStyle.left = ghostLeft;
1480
+ panelStyle.top = ghostTop;
1481
+ transform = wrapper(panel);
1482
+ transform.moveTo((lastX + sX), (lastY + sY));
1483
+ resize(transform, panelStyle, parseFloat(ghostWidth), parseFloat(ghostHeight));
1462
1484
  }
1463
1485
  if (setOrigin)
1464
1486
  panel.style.transformOrigin = originalTransformOrigin;
@@ -1479,9 +1501,6 @@
1479
1501
  }
1480
1502
  }
1481
1503
  }
1482
- handle.classList.remove(CLASS_RESIZABLE_HANDLE_ACTIVE);
1483
- onEnd &&
1484
- onEnd.call(uiik, { w: currentW, h: currentH, transform }, ev);
1485
1504
  });
1486
1505
  }, {
1487
1506
  threshold: THRESHOLD,
@@ -1498,8 +1517,17 @@
1498
1517
  else if (is.isFunction(handleStr)) {
1499
1518
  handles = handleStr(panel);
1500
1519
  }
1520
+ else if (myfx.isElement(handleStr)) {
1521
+ handles = [handleStr];
1522
+ }
1523
+ else if (is.isArrayLike(handleStr)) {
1524
+ let eles = myfx.filter(handleStr, h => myfx.isElement(h));
1525
+ if (eles.length > 0) {
1526
+ handles = eles;
1527
+ }
1528
+ }
1501
1529
  if (!handles) {
1502
- console.error('Can not find handles with "' + panel.outerHTML + '"');
1530
+ console.error('Can not find handles in "' + panel.outerHTML + '"');
1503
1531
  return;
1504
1532
  }
1505
1533
  handles = is.isArrayLike(handles) ? handles : [handles];
@@ -2969,7 +2997,7 @@
2969
2997
  return new Sortable(container, opts);
2970
2998
  }
2971
2999
 
2972
- var version = "1.3.6";
3000
+ var version = "1.4.0";
2973
3001
  var repository = {
2974
3002
  type: "git",
2975
3003
  url: "https://github.com/holyhigh2/uiik"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uiik",
3
- "version": "1.3.6",
3
+ "version": "1.4.0",
4
4
  "description": "A UI interactions kit includes draggable, splittable, rotatable, selectable, etc.",
5
5
  "main": "index.js",
6
6
  "module": "index.esm.js",
package/types.d.ts CHANGED
@@ -21,12 +21,11 @@ export declare abstract class Uii {
21
21
  protected onOptionChanged(opts?: Record<string, any>): void;
22
22
  }
23
23
  export type ResizableOptions = {
24
- handle?: ((target: HTMLElement | SVGGraphicsElement) => NodeList | HTMLCollection | HTMLElement[] | HTMLElement | SVGGraphicsElement) | string | NodeList | HTMLCollection | HTMLElement[] | HTMLElement | SVGGraphicsElement;
24
+ handle: ((target: HTMLElement | SVGGraphicsElement) => NodeList | HTMLCollection | HTMLElement[] | HTMLElement | SVGGraphicsElement) | string | NodeList | HTMLCollection | HTMLElement[] | HTMLElement | SVGGraphicsElement;
25
25
  minSize?: number | Array<number>;
26
26
  maxSize?: number | Array<number>;
27
- dir?: string[];
28
27
  aspectRatio?: number;
29
- ghost?: boolean | Function;
28
+ ghost?: ((panel: HTMLElement | SVGGraphicsElement) => HTMLElement | SVGGraphicsElement) | boolean;
30
29
  ghostClass?: string;
31
30
  ox?: number | string;
32
31
  oy?: number | string;
@@ -35,6 +34,8 @@ export type ResizableOptions = {
35
34
  w: number;
36
35
  h: number;
37
36
  transform: UiiTransform;
37
+ handle: HTMLElement | SVGGraphicsElement;
38
+ ghost: HTMLElement | SVGGraphicsElement;
38
39
  }, event: MouseEvent) => void;
39
40
  onResize?: (data: {
40
41
  w: number;
@@ -47,14 +48,17 @@ export type ResizableOptions = {
47
48
  y: number;
48
49
  }>;
49
50
  transform: UiiTransform;
50
- }, event: MouseEvent) => void;
51
+ handle: HTMLElement | SVGGraphicsElement;
52
+ }, event: MouseEvent) => boolean | void;
51
53
  onEnd?: (data: {
52
54
  w: number;
53
55
  h: number;
54
56
  transform: UiiTransform;
55
- }, event: MouseEvent) => void;
57
+ handle: HTMLElement | SVGGraphicsElement;
58
+ ghost: HTMLElement | SVGGraphicsElement;
59
+ }, event: MouseEvent) => boolean | void;
56
60
  onClone?: (data: {
57
- clone: HTMLElement;
61
+ clone: HTMLElement | SVGGraphicsElement;
58
62
  }, event: MouseEvent) => void;
59
63
  };
60
64
  export type SplittableOptions = {
@@ -98,7 +102,7 @@ export type DraggableOptions = {
98
102
  handle?: string;
99
103
  filter?: string;
100
104
  droppable?: (() => NodeList | HTMLCollection | HTMLElement[]) | string | HTMLElement | HTMLElement[];
101
- ghost?: ((el: HTMLElement) => HTMLElement) | boolean;
105
+ ghost?: ((panel: HTMLElement | SVGGraphicsElement) => HTMLElement | SVGGraphicsElement) | boolean;
102
106
  ghostClass?: string;
103
107
  ghostTo?: string | HTMLElement;
104
108
  direction?: "v" | "h";