@haiilo/catalyst 0.3.2 → 0.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.
Files changed (39) hide show
  1. package/dist/catalyst/catalyst.esm.js +1 -1
  2. package/dist/catalyst/catalyst.esm.js.map +1 -1
  3. package/dist/catalyst/p-89a97b7b.entry.js +10 -0
  4. package/dist/catalyst/p-89a97b7b.entry.js.map +1 -0
  5. package/dist/cjs/{cat-alert_8.cjs.entry.js → cat-alert_9.cjs.entry.js} +158 -51
  6. package/dist/cjs/cat-alert_9.cjs.entry.js.map +1 -0
  7. package/dist/cjs/catalyst.cjs.js +1 -1
  8. package/dist/cjs/loader.cjs.js +1 -1
  9. package/dist/collection/collection-manifest.json +2 -1
  10. package/dist/collection/components/cat-menu/cat-menu.js +3 -5
  11. package/dist/collection/components/cat-menu/cat-menu.js.map +1 -1
  12. package/dist/collection/components/cat-tooltip/cat-tooltip.css +37 -0
  13. package/dist/collection/components/cat-tooltip/cat-tooltip.js +254 -0
  14. package/dist/collection/components/cat-tooltip/cat-tooltip.js.map +1 -0
  15. package/dist/collection/utils/first-tabbable.js +6 -0
  16. package/dist/collection/utils/first-tabbable.js.map +1 -0
  17. package/dist/collection/utils/is-touch-screen.js +3 -0
  18. package/dist/collection/utils/is-touch-screen.js.map +1 -0
  19. package/dist/components/cat-menu.js +11 -1519
  20. package/dist/components/cat-menu.js.map +1 -1
  21. package/dist/components/cat-tooltip.d.ts +11 -0
  22. package/dist/components/cat-tooltip.js +154 -0
  23. package/dist/components/cat-tooltip.js.map +1 -0
  24. package/dist/components/first-tabbable.js +1495 -0
  25. package/dist/components/first-tabbable.js.map +1 -0
  26. package/dist/esm/{cat-alert_8.entry.js → cat-alert_9.entry.js} +158 -52
  27. package/dist/esm/cat-alert_9.entry.js.map +1 -0
  28. package/dist/esm/catalyst.js +1 -1
  29. package/dist/esm/loader.js +1 -1
  30. package/dist/types/components/cat-menu/cat-menu.d.ts +0 -1
  31. package/dist/types/components/cat-tooltip/cat-tooltip.d.ts +46 -0
  32. package/dist/types/components.d.ts +61 -0
  33. package/dist/types/utils/first-tabbable.d.ts +4 -0
  34. package/dist/types/utils/is-touch-screen.d.ts +2 -0
  35. package/package.json +7 -7
  36. package/dist/catalyst/p-31b500c7.entry.js +0 -10
  37. package/dist/catalyst/p-31b500c7.entry.js.map +0 -1
  38. package/dist/cjs/cat-alert_8.cjs.entry.js.map +0 -1
  39. package/dist/esm/cat-alert_8.entry.js.map +0 -1
@@ -1753,7 +1753,7 @@ const computePosition = (reference, floating, options) => computePosition$1(refe
1753
1753
  });
1754
1754
 
1755
1755
  /*!
1756
- * tabbable 5.3.0-beta.1
1756
+ * tabbable 5.3.1
1757
1757
  * @license MIT, https://github.com/focus-trap/tabbable/blob/master/LICENSE
1758
1758
  */
1759
1759
  var candidateSelectors = ['input', 'select', 'textarea', 'a[href]', 'button', '[tabindex]:not(slot)', 'audio[controls]', 'video[controls]', '[contenteditable]:not([contenteditable="false"])', 'details>summary:first-of-type', 'details'];
@@ -1872,34 +1872,22 @@ var getCandidatesIteratively = function getCandidatesIteratively(elements, inclu
1872
1872
  return candidates;
1873
1873
  };
1874
1874
 
1875
- var isContentEditable = function isContentEditable(node) {
1876
- return node.contentEditable === 'true';
1877
- };
1878
-
1879
1875
  var getTabindex = function getTabindex(node, isScope) {
1880
- var tabindexAttr = parseInt(node.getAttribute('tabindex'), 10);
1881
-
1882
- if (!isNaN(tabindexAttr)) {
1883
- return tabindexAttr;
1884
- } // Browsers do not return `tabIndex` correctly for contentEditable nodes;
1885
- // so if they don't have a tabindex attribute specifically set, assume it's 0.
1886
-
1887
-
1888
- if (isContentEditable(node)) {
1889
- return 0;
1890
- } // in Chrome, <details/>, <audio controls/> and <video controls/> elements get a default
1891
- // `tabIndex` of -1 when the 'tabindex' attribute isn't specified in the DOM,
1892
- // yet they are still part of the regular tab order; in FF, they get a default
1893
- // `tabIndex` of 0; since Chrome still puts those elements in the regular tab
1894
- // order, consider their tab index to be 0.
1895
- //
1896
- // isScope is positive for custom element with shadow root or slot that by default
1897
- // have tabIndex -1, but need to be sorted by document order in order for their
1898
- // content to be inserted in the correct position
1899
-
1900
-
1901
- if ((isScope || node.nodeName === 'AUDIO' || node.nodeName === 'VIDEO' || node.nodeName === 'DETAILS') && node.getAttribute('tabindex') === null) {
1902
- return 0;
1876
+ if (node.tabIndex < 0) {
1877
+ // in Chrome, <details/>, <audio controls/> and <video controls/> elements get a default
1878
+ // `tabIndex` of -1 when the 'tabindex' attribute isn't specified in the DOM,
1879
+ // yet they are still part of the regular tab order; in FF, they get a default
1880
+ // `tabIndex` of 0; since Chrome still puts those elements in the regular tab
1881
+ // order, consider their tab index to be 0.
1882
+ // Also browsers do not return `tabIndex` correctly for contentEditable nodes;
1883
+ // so if they don't have a tabindex attribute specifically set, assume it's 0.
1884
+ //
1885
+ // isScope is positive for custom element with shadow root or slot that by default
1886
+ // have tabIndex -1, but need to be sorted by document order in order for their
1887
+ // content to be inserted in the correct position
1888
+ if ((isScope || /^(AUDIO|VIDEO|DETAILS)$/.test(node.tagName) || node.isContentEditable) && isNaN(parseInt(node.getAttribute('tabindex'), 10))) {
1889
+ return 0;
1890
+ }
1903
1891
  }
1904
1892
 
1905
1893
  return node.tabIndex;
@@ -2082,7 +2070,7 @@ var isNodeMatchingSelectorFocusable = function isNodeMatchingSelectorFocusable(o
2082
2070
  };
2083
2071
 
2084
2072
  var isNodeMatchingSelectorTabbable = function isNodeMatchingSelectorTabbable(options, node) {
2085
- if (!isNodeMatchingSelectorFocusable(options, node) || isNonTabbableRadio(node) || getTabindex(node) < 0) {
2073
+ if (isNonTabbableRadio(node) || getTabindex(node) < 0 || !isNodeMatchingSelectorFocusable(options, node)) {
2086
2074
  return false;
2087
2075
  }
2088
2076
 
@@ -2186,7 +2174,7 @@ var isFocusable = function isFocusable(node, options) {
2186
2174
  };
2187
2175
 
2188
2176
  /*!
2189
- * focus-trap 6.8.0-beta.2
2177
+ * focus-trap 6.8.1
2190
2178
  * @license MIT, https://github.com/focus-trap/focus-trap/blob/master/LICENSE
2191
2179
  */
2192
2180
 
@@ -2483,16 +2471,10 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
2483
2471
 
2484
2472
  var updateTabbableNodes = function updateTabbableNodes() {
2485
2473
  state.containerGroups = state.containers.map(function (container) {
2486
- var _config$tabbableOptio, _config$tabbableOptio2;
2487
-
2488
- var tabbableNodes = tabbable(container, {
2489
- getShadowRoot: (_config$tabbableOptio = config.tabbableOptions) === null || _config$tabbableOptio === void 0 ? void 0 : _config$tabbableOptio.getShadowRoot
2490
- }); // NOTE: if we have tabbable nodes, we must have focusable nodes; focusable nodes
2474
+ var tabbableNodes = tabbable(container, config.tabbableOptions); // NOTE: if we have tabbable nodes, we must have focusable nodes; focusable nodes
2491
2475
  // are a superset of tabbable nodes
2492
2476
 
2493
- var focusableNodes = focusable(container, {
2494
- getShadowRoot: (_config$tabbableOptio2 = config.tabbableOptions) === null || _config$tabbableOptio2 === void 0 ? void 0 : _config$tabbableOptio2.getShadowRoot
2495
- });
2477
+ var focusableNodes = focusable(container, config.tabbableOptions);
2496
2478
  return {
2497
2479
  container: container,
2498
2480
  tabbableNodes: tabbableNodes,
@@ -2530,12 +2512,12 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
2530
2512
 
2531
2513
  if (forward) {
2532
2514
  return focusableNodes.slice(nodeIdx + 1).find(function (n) {
2533
- return isTabbable(n);
2515
+ return isTabbable(n, config.tabbableOptions);
2534
2516
  });
2535
2517
  }
2536
2518
 
2537
2519
  return focusableNodes.slice(0, nodeIdx).reverse().find(function (n) {
2538
- return isTabbable(n);
2520
+ return isTabbable(n, config.tabbableOptions);
2539
2521
  });
2540
2522
  }
2541
2523
  };
@@ -2603,7 +2585,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
2603
2585
  // that was clicked, whether it's focusable or not; by setting
2604
2586
  // `returnFocus: true`, we'll attempt to re-focus the node originally-focused
2605
2587
  // on activation (or the configured `setReturnFocus` node)
2606
- returnFocus: config.returnFocusOnDeactivate && !isFocusable(target)
2588
+ returnFocus: config.returnFocusOnDeactivate && !isFocusable(target, config.tabbableOptions)
2607
2589
  });
2608
2590
  return;
2609
2591
  } // This is needed for mobile devices.
@@ -2670,7 +2652,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
2670
2652
  return target === firstTabbableNode;
2671
2653
  });
2672
2654
 
2673
- if (startOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target) && !isTabbable(target) && !containerGroup.nextTabbableNode(target, false))) {
2655
+ if (startOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target, config.tabbableOptions) && !isTabbable(target, config.tabbableOptions) && !containerGroup.nextTabbableNode(target, false))) {
2674
2656
  // an exception case where the target is either the container itself, or
2675
2657
  // a non-tabbable node that was given focus (i.e. tabindex is negative
2676
2658
  // and user clicked on it or node was programmatically given focus)
@@ -2696,7 +2678,7 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
2696
2678
  return target === lastTabbableNode;
2697
2679
  });
2698
2680
 
2699
- if (lastOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target) && !isTabbable(target) && !containerGroup.nextTabbableNode(target))) {
2681
+ if (lastOfGroupIndex < 0 && (containerGroup.container === target || isFocusable(target, config.tabbableOptions) && !isTabbable(target, config.tabbableOptions) && !containerGroup.nextTabbableNode(target))) {
2700
2682
  // an exception case where the target is the container itself, or
2701
2683
  // a non-tabbable node that was given focus (i.e. tabindex is negative
2702
2684
  // and user clicked on it or node was programmatically given focus)
@@ -2932,15 +2914,19 @@ var createFocusTrap = function createFocusTrap(elements, userOptions) {
2932
2914
  return trap;
2933
2915
  };
2934
2916
 
2917
+ const firstTabbable = (container) => {
2918
+ return (container ? tabbable(container, { includeContainer: true, getShadowRoot: true }) : []).shift();
2919
+ };
2920
+
2935
2921
  const catMenuCss = ":host{display:inline-block}:host([hidden]){display:none}.content{padding-top:0.5rem;padding-bottom:0.5rem;position:absolute;background:white;display:none;overflow:auto;-webkit-overflow-scrolling:touch;min-width:8rem;max-width:16rem;min-height:2rem;max-height:calc(100vh - 48px);box-shadow:0 1px 4px 0 rgba(16, 29, 48, 0.2);border-radius:0.25rem}";
2936
2922
 
2937
- let nextUniqueId = 0;
2923
+ let nextUniqueId$1 = 0;
2938
2924
  const CatMenu = class {
2939
2925
  constructor(hostRef) {
2940
2926
  index.registerInstance(this, hostRef);
2941
2927
  this.catOpen = index.createEvent(this, "catOpen", 7);
2942
2928
  this.catClose = index.createEvent(this, "catClose", 7);
2943
- this.id = nextUniqueId++;
2929
+ this.id = nextUniqueId$1++;
2944
2930
  /**
2945
2931
  * The placement of the menu.
2946
2932
  */
@@ -2956,7 +2942,7 @@ const CatMenu = class {
2956
2942
  }
2957
2943
  componentDidLoad() {
2958
2944
  var _a, _b, _c, _d, _e;
2959
- this.trigger = this.firstTabbable(this.triggerSlot);
2945
+ this.trigger = firstTabbable(this.triggerSlot);
2960
2946
  (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.setAttribute('aria-haspopup', 'true');
2961
2947
  (_b = this.trigger) === null || _b === void 0 ? void 0 : _b.setAttribute('aria-expanded', 'false');
2962
2948
  (_c = this.trigger) === null || _c === void 0 ? void 0 : _c.setAttribute('aria-controls', this.contentId);
@@ -2968,7 +2954,7 @@ const CatMenu = class {
2968
2954
  this.keyListener = event => {
2969
2955
  if (this.content && ['ArrowDown', 'ArrowUp'].includes(event.key)) {
2970
2956
  const targetElements = tabbable(this.content, { includeContainer: false, getShadowRoot: true });
2971
- const activeElement = this.firstTabbable(document.activeElement);
2957
+ const activeElement = firstTabbable(document.activeElement);
2972
2958
  const activeIdx = activeElement ? targetElements.indexOf(activeElement) : -1;
2973
2959
  const activeOff = event.key === 'ArrowDown' ? 1 : -1;
2974
2960
  const targetIdx = activeIdx < 0 ? 0 : (activeIdx + activeOff + targetElements.length) % targetElements.length;
@@ -3031,9 +3017,6 @@ const CatMenu = class {
3031
3017
  });
3032
3018
  }
3033
3019
  }
3034
- firstTabbable(container) {
3035
- return (container ? tabbable(container, { includeContainer: true, getShadowRoot: true }) : []).shift();
3036
- }
3037
3020
  };
3038
3021
  CatMenu.OFFSET = 4;
3039
3022
  CatMenu.style = catMenuCss;
@@ -4438,6 +4421,129 @@ const CatSpinner = class {
4438
4421
  };
4439
4422
  CatSpinner.style = catSpinnerCss;
4440
4423
 
4424
+ const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0;
4425
+
4426
+ const catTooltipCss = ":host{display:contents}:host([hidden]){display:none}.tooltip{position:absolute;font-size:0.875rem;line-height:1rem;padding:0.25rem;background-color:rgba(0, 0, 0, 0.7);border-radius:0.125rem;color:white;white-space:nowrap;transition:0.13s linear;visibility:hidden;opacity:0}.tooltip-show{opacity:1;visibility:visible}.tooltip-trigger{display:inline-block}.tooltip-trigger:focus{outline:none}";
4427
+
4428
+ let nextUniqueId = 0;
4429
+ const CatTooltip = class {
4430
+ constructor(hostRef) {
4431
+ index.registerInstance(this, hostRef);
4432
+ this.id = `cat-tooltip-${nextUniqueId++}`;
4433
+ /**
4434
+ * The content of the tooltip.
4435
+ */
4436
+ this.content = '';
4437
+ /**
4438
+ * Specifies that the tooltip should be disabled. A disabled tooltip is unusable,
4439
+ * and invisible. Corresponds with the native HTML disabled attribute.
4440
+ */
4441
+ this.disabled = false;
4442
+ /**
4443
+ * The placement of the tooltip.
4444
+ */
4445
+ this.placement = 'top';
4446
+ /**
4447
+ * The delay time for showing tooltip in ms.
4448
+ */
4449
+ this.showDelay = 1000;
4450
+ /**
4451
+ * The delay time for hiding tooltip in ms.
4452
+ */
4453
+ this.hideDelay = 0;
4454
+ /**
4455
+ * The duration of tap to show the tooltip.
4456
+ */
4457
+ this.longTouchDuration = 1000;
4458
+ }
4459
+ handleKeyDown({ key }) {
4460
+ key === 'Escape' && this.hideListener();
4461
+ }
4462
+ componentDidLoad() {
4463
+ var _a, _b, _c, _d, _e, _f, _g;
4464
+ this.trigger = firstTabbable(this.triggerElement) || this.triggerElement;
4465
+ if (!this.isTabbable) {
4466
+ (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.setAttribute('tabindex', '0');
4467
+ }
4468
+ if (this.trigger && this.tooltip) {
4469
+ autoUpdate(this.trigger, this.tooltip, () => this.update());
4470
+ }
4471
+ if (isTouchDevice) {
4472
+ (_b = this.trigger) === null || _b === void 0 ? void 0 : _b.addEventListener('touchstart', this.touchStartListener.bind(this));
4473
+ (_c = this.trigger) === null || _c === void 0 ? void 0 : _c.addEventListener('touchend', this.touchEndListener.bind(this));
4474
+ }
4475
+ else {
4476
+ (_d = this.trigger) === null || _d === void 0 ? void 0 : _d.addEventListener('focusin', this.showListener.bind(this));
4477
+ (_e = this.trigger) === null || _e === void 0 ? void 0 : _e.addEventListener('focusout', this.hideListener.bind(this));
4478
+ (_f = this.trigger) === null || _f === void 0 ? void 0 : _f.addEventListener('mouseenter', this.showListener.bind(this));
4479
+ (_g = this.trigger) === null || _g === void 0 ? void 0 : _g.addEventListener('mouseleave', this.hideListener.bind(this));
4480
+ }
4481
+ }
4482
+ disconnectedCallback() {
4483
+ var _a, _b, _c, _d, _e, _f;
4484
+ if (isTouchDevice) {
4485
+ (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.removeEventListener('touchstart', this.touchStartListener.bind(this));
4486
+ (_b = this.trigger) === null || _b === void 0 ? void 0 : _b.removeEventListener('touchend', this.touchEndListener.bind(this));
4487
+ }
4488
+ else {
4489
+ (_c = this.trigger) === null || _c === void 0 ? void 0 : _c.removeEventListener('mouseenter', this.showListener.bind(this));
4490
+ (_d = this.trigger) === null || _d === void 0 ? void 0 : _d.removeEventListener('mouseleave', this.hideListener.bind(this));
4491
+ (_e = this.trigger) === null || _e === void 0 ? void 0 : _e.removeEventListener('focusin', this.showListener.bind(this));
4492
+ (_f = this.trigger) === null || _f === void 0 ? void 0 : _f.removeEventListener('focusout', this.hideListener.bind(this));
4493
+ }
4494
+ }
4495
+ render() {
4496
+ return (index.h(index.Host, null, index.h("div", { ref: el => (this.triggerElement = el), "aria-describedby": this.id, class: "tooltip-trigger" }, index.h("slot", null)), this.content && !this.disabled && (index.h("div", { ref: el => (this.tooltip = el), id: this.id, class: "tooltip" }, this.content))));
4497
+ }
4498
+ get isTabbable() {
4499
+ return firstTabbable(this.trigger);
4500
+ }
4501
+ update() {
4502
+ if (this.trigger && this.tooltip) {
4503
+ computePosition(this.trigger, this.tooltip, {
4504
+ placement: this.placement,
4505
+ middleware: [offset(CatTooltip.OFFSET), flip()]
4506
+ }).then(({ x, y }) => {
4507
+ if (this.tooltip) {
4508
+ Object.assign(this.tooltip.style, {
4509
+ left: `${Math.max(0, x)}px`,
4510
+ top: `${y}px`
4511
+ });
4512
+ }
4513
+ });
4514
+ }
4515
+ }
4516
+ showListener() {
4517
+ window.clearTimeout(this.hideTimeout);
4518
+ this.showTimeout = window.setTimeout(() => {
4519
+ var _a, _b;
4520
+ (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.focus();
4521
+ (_b = this.tooltip) === null || _b === void 0 ? void 0 : _b.classList.add('tooltip-show');
4522
+ }, this.showDelay);
4523
+ }
4524
+ hideListener() {
4525
+ window.clearTimeout(this.showTimeout);
4526
+ this.hideTimeout = window.setTimeout(() => {
4527
+ var _a, _b;
4528
+ (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.blur();
4529
+ (_b = this.tooltip) === null || _b === void 0 ? void 0 : _b.classList.remove('tooltip-show');
4530
+ }, this.hideDelay);
4531
+ }
4532
+ touchStartListener() {
4533
+ this.touchTimeout = window.setTimeout(() => {
4534
+ var _a;
4535
+ (_a = this.tooltip) === null || _a === void 0 ? void 0 : _a.classList.add('tooltip-show');
4536
+ }, this.longTouchDuration);
4537
+ }
4538
+ touchEndListener() {
4539
+ var _a;
4540
+ window.clearTimeout(this.touchTimeout);
4541
+ (_a = this.tooltip) === null || _a === void 0 ? void 0 : _a.classList.remove('tooltip-show');
4542
+ }
4543
+ };
4544
+ CatTooltip.OFFSET = 4;
4545
+ CatTooltip.style = catTooltipCss;
4546
+
4441
4547
  exports.cat_alert = CatAlert;
4442
4548
  exports.cat_badge = CatBadge;
4443
4549
  exports.cat_button = CatButton;
@@ -4446,5 +4552,6 @@ exports.cat_menu = CatMenu;
4446
4552
  exports.cat_scrollable = CatScrollable;
4447
4553
  exports.cat_skeleton = CatSkeleton;
4448
4554
  exports.cat_spinner = CatSpinner;
4555
+ exports.cat_tooltip = CatTooltip;
4449
4556
 
4450
- //# sourceMappingURL=cat-alert_8.cjs.entry.js.map
4557
+ //# sourceMappingURL=cat-alert_9.cjs.entry.js.map