@unabridged/midwest 0.12.0 → 0.13.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.
@@ -17,6 +17,8 @@ export { default as CountdownTimer } from '../../../components/midwest/countdown
17
17
  import Badge from '../../../components/midwest/badge_component/badge_component_controller.js';
18
18
  import ConfirmationController from '../../../components/midwest/confirmation_component/confirmation_component_controller.js';
19
19
  import AvatarGroup from '../../../components/midwest/avatar_group_component/avatar_group_component_controller.js';
20
+ import Chart from '../../../components/midwest/chart_component/chart_component_controller.js';
21
+ export { default as Chart } from '../../../components/midwest/chart_component/chart_component_controller.js';
20
22
 
21
23
  function registerMidwestControllers(application) {
22
24
  application.register("midwest-card", Card);
@@ -35,6 +37,7 @@ function registerMidwestControllers(application) {
35
37
  application.register("midwest-badge", Badge);
36
38
  application.register("midwest-confirmation", ConfirmationController);
37
39
  application.register("midwest-avatar-group", AvatarGroup);
40
+ application.register("midwest-chart", Chart);
38
41
  }
39
42
 
40
43
  export { registerMidwestControllers };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../../../../app/assets/javascript/midwest/index.ts"],"sourcesContent":["import Card from '../../../components/midwest/card_component/card_component_controller'\nimport Banner from '../../../components/midwest/banner_component/banner_component_controller'\nimport Input from '../../../components/midwest/form/input_component/input_component_controller'\nimport File from '../../../components/midwest/form/file_component/file_component_controller'\nimport Dropdown from '../../../components/midwest/dropdown_component/dropdown_component_controller'\nimport Prose from '../../../components/midwest/prose_component/prose_component_controller'\nimport Dialog from '../../../components/midwest/dialog_component/dialog_component_controller'\nimport Tabs from '../../../components/midwest/tabs_component/tabs_component_controller'\nimport Tooltip from '../../../components/midwest/tooltip_component/tooltip_component_controller'\nimport Carousel from '../../../components/midwest/carousel_component/carousel_component_controller'\nimport FormLiveSummary from '../../../components/midwest/form/live_summary_component/live_summary_component_controller'\nimport Form from '../../../components/midwest/form/form_controller'\nimport CountdownTimer from '../../../components/midwest/countdown_timer_component/countdown_timer_component_controller'\nimport Badge from '../../../components/midwest/badge_component/badge_component_controller'\nimport Confirmation from '../../../components/midwest/confirmation_component/confirmation_component_controller'\nimport AvatarGroup from '../../../components/midwest/avatar_group_component/avatar_group_component_controller'\n/* IMPORTS */\n\nexport { Card, Banner, CountdownTimer }\n\nexport function registerMidwestControllers (application: any) {\n application.register('midwest-card', Card)\n application.register('midwest-banner', Banner)\n application.register('midwest-countdown-timer', CountdownTimer)\n application.register('midwest-input', Input)\n application.register('midwest-file', File)\n application.register('midwest-dropdown', Dropdown)\n application.register('midwest-prose', Prose)\n application.register('midwest-dialog', Dialog)\n application.register('midwest-tabs', Tabs)\n application.register('midwest-tooltip', Tooltip)\n application.register('midwest-carousel', Carousel)\n application.register('midwest-form-live-summary', FormLiveSummary)\n application.register('midwest-form', Form)\n application.register('midwest-badge', Badge)\n application.register('midwest-confirmation', Confirmation)\n application.register('midwest-avatar-group', AvatarGroup)\n /* EXPORTS */\n}\n"],"names":["Confirmation"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBO,SAAS,2BAA4B,WAAkB,EAAA;AAC5D,EAAY,WAAA,CAAA,QAAA,CAAS,gBAAgB,IAAI,CAAA,CAAA;AACzC,EAAY,WAAA,CAAA,QAAA,CAAS,kBAAkB,MAAM,CAAA,CAAA;AAC7C,EAAY,WAAA,CAAA,QAAA,CAAS,2BAA2B,cAAc,CAAA,CAAA;AAC9D,EAAY,WAAA,CAAA,QAAA,CAAS,iBAAiB,KAAK,CAAA,CAAA;AAC3C,EAAY,WAAA,CAAA,QAAA,CAAS,gBAAgB,IAAI,CAAA,CAAA;AACzC,EAAY,WAAA,CAAA,QAAA,CAAS,oBAAoB,QAAQ,CAAA,CAAA;AACjD,EAAY,WAAA,CAAA,QAAA,CAAS,iBAAiB,KAAK,CAAA,CAAA;AAC3C,EAAY,WAAA,CAAA,QAAA,CAAS,kBAAkB,MAAM,CAAA,CAAA;AAC7C,EAAY,WAAA,CAAA,QAAA,CAAS,gBAAgB,IAAI,CAAA,CAAA;AACzC,EAAY,WAAA,CAAA,QAAA,CAAS,mBAAmB,OAAO,CAAA,CAAA;AAC/C,EAAY,WAAA,CAAA,QAAA,CAAS,oBAAoB,QAAQ,CAAA,CAAA;AACjD,EAAY,WAAA,CAAA,QAAA,CAAS,6BAA6B,eAAe,CAAA,CAAA;AACjE,EAAY,WAAA,CAAA,QAAA,CAAS,gBAAgB,IAAI,CAAA,CAAA;AACzC,EAAY,WAAA,CAAA,QAAA,CAAS,iBAAiB,KAAK,CAAA,CAAA;AAC3C,EAAY,WAAA,CAAA,QAAA,CAAS,wBAAwBA,sBAAY,CAAA,CAAA;AACzD,EAAY,WAAA,CAAA,QAAA,CAAS,wBAAwB,WAAW,CAAA,CAAA;AAE1D;;;;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../../../../app/assets/javascript/midwest/index.ts"],"sourcesContent":["import Card from '../../../components/midwest/card_component/card_component_controller'\nimport Banner from '../../../components/midwest/banner_component/banner_component_controller'\nimport Input from '../../../components/midwest/form/input_component/input_component_controller'\nimport File from '../../../components/midwest/form/file_component/file_component_controller'\nimport Dropdown from '../../../components/midwest/dropdown_component/dropdown_component_controller'\nimport Prose from '../../../components/midwest/prose_component/prose_component_controller'\nimport Dialog from '../../../components/midwest/dialog_component/dialog_component_controller'\nimport Tabs from '../../../components/midwest/tabs_component/tabs_component_controller'\nimport Tooltip from '../../../components/midwest/tooltip_component/tooltip_component_controller'\nimport Carousel from '../../../components/midwest/carousel_component/carousel_component_controller'\nimport FormLiveSummary from '../../../components/midwest/form/live_summary_component/live_summary_component_controller'\nimport Form from '../../../components/midwest/form/form_controller'\nimport CountdownTimer from '../../../components/midwest/countdown_timer_component/countdown_timer_component_controller'\nimport Badge from '../../../components/midwest/badge_component/badge_component_controller'\nimport Confirmation from '../../../components/midwest/confirmation_component/confirmation_component_controller'\nimport AvatarGroup from '../../../components/midwest/avatar_group_component/avatar_group_component_controller'\nimport Chart from '../../../components/midwest/chart_component/chart_component_controller'\n/* IMPORTS */\n\nexport { Card, Banner, CountdownTimer, Chart }\n\nexport function registerMidwestControllers (application: any) {\n application.register('midwest-card', Card)\n application.register('midwest-banner', Banner)\n application.register('midwest-countdown-timer', CountdownTimer)\n application.register('midwest-input', Input)\n application.register('midwest-file', File)\n application.register('midwest-dropdown', Dropdown)\n application.register('midwest-prose', Prose)\n application.register('midwest-dialog', Dialog)\n application.register('midwest-tabs', Tabs)\n application.register('midwest-tooltip', Tooltip)\n application.register('midwest-carousel', Carousel)\n application.register('midwest-form-live-summary', FormLiveSummary)\n application.register('midwest-form', Form)\n application.register('midwest-badge', Badge)\n application.register('midwest-confirmation', Confirmation)\n application.register('midwest-avatar-group', AvatarGroup)\n application.register('midwest-chart', Chart)\n /* EXPORTS */\n}\n"],"names":["Confirmation"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAqBO,SAAS,2BAA4B,WAAkB,EAAA;AAC5D,EAAY,WAAA,CAAA,QAAA,CAAS,gBAAgB,IAAI,CAAA,CAAA;AACzC,EAAY,WAAA,CAAA,QAAA,CAAS,kBAAkB,MAAM,CAAA,CAAA;AAC7C,EAAY,WAAA,CAAA,QAAA,CAAS,2BAA2B,cAAc,CAAA,CAAA;AAC9D,EAAY,WAAA,CAAA,QAAA,CAAS,iBAAiB,KAAK,CAAA,CAAA;AAC3C,EAAY,WAAA,CAAA,QAAA,CAAS,gBAAgB,IAAI,CAAA,CAAA;AACzC,EAAY,WAAA,CAAA,QAAA,CAAS,oBAAoB,QAAQ,CAAA,CAAA;AACjD,EAAY,WAAA,CAAA,QAAA,CAAS,iBAAiB,KAAK,CAAA,CAAA;AAC3C,EAAY,WAAA,CAAA,QAAA,CAAS,kBAAkB,MAAM,CAAA,CAAA;AAC7C,EAAY,WAAA,CAAA,QAAA,CAAS,gBAAgB,IAAI,CAAA,CAAA;AACzC,EAAY,WAAA,CAAA,QAAA,CAAS,mBAAmB,OAAO,CAAA,CAAA;AAC/C,EAAY,WAAA,CAAA,QAAA,CAAS,oBAAoB,QAAQ,CAAA,CAAA;AACjD,EAAY,WAAA,CAAA,QAAA,CAAS,6BAA6B,eAAe,CAAA,CAAA;AACjE,EAAY,WAAA,CAAA,QAAA,CAAS,gBAAgB,IAAI,CAAA,CAAA;AACzC,EAAY,WAAA,CAAA,QAAA,CAAS,iBAAiB,KAAK,CAAA,CAAA;AAC3C,EAAY,WAAA,CAAA,QAAA,CAAS,wBAAwBA,sBAAY,CAAA,CAAA;AACzD,EAAY,WAAA,CAAA,QAAA,CAAS,wBAAwB,WAAW,CAAA,CAAA;AACxD,EAAY,WAAA,CAAA,QAAA,CAAS,iBAAiB,KAAK,CAAA,CAAA;AAE7C;;;;"}
@@ -0,0 +1,88 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+
3
+ class Chart extends Controller {
4
+ static targets = ["tooltip", "svg"];
5
+ static values = { tooltipEnabled: { type: Boolean, default: true } };
6
+ connect() {
7
+ if (this.tooltipEnabledValue && this.hasTooltipTarget) {
8
+ this.attachListeners();
9
+ }
10
+ }
11
+ disconnect() {
12
+ if (!this.hasSvgTarget)
13
+ return;
14
+ this.svgTarget.removeEventListener("pointerover", this.showTooltipOnPointer);
15
+ this.svgTarget.removeEventListener("pointermove", this.moveTooltip);
16
+ this.svgTarget.removeEventListener("pointerout", this.hideTooltip);
17
+ this.svgTarget.removeEventListener("focusin", this.showTooltipOnFocus);
18
+ this.svgTarget.removeEventListener("focusout", this.hideTooltip);
19
+ }
20
+ attachListeners() {
21
+ this.svgTarget.addEventListener("pointerover", this.showTooltipOnPointer);
22
+ this.svgTarget.addEventListener("pointermove", this.moveTooltip);
23
+ this.svgTarget.addEventListener("pointerout", this.hideTooltip);
24
+ this.svgTarget.addEventListener("focusin", this.showTooltipOnFocus);
25
+ this.svgTarget.addEventListener("focusout", this.hideTooltip);
26
+ }
27
+ // Arrow functions so `this` is stable for add/removeEventListener pairing.
28
+ showTooltipOnPointer = (event) => {
29
+ if (!this.hasTooltipTarget)
30
+ return;
31
+ const target = event.target.closest("[data-tooltip-content]");
32
+ if (!target)
33
+ return;
34
+ this.tooltipTarget.textContent = target.dataset.tooltipContent ?? "";
35
+ this.tooltipTarget.classList.add("is-visible");
36
+ this.positionAtPointer(event);
37
+ };
38
+ // Reposition tooltip as the pointer moves within the SVG so it tracks the cursor.
39
+ moveTooltip = (event) => {
40
+ if (!this.tooltipTarget.classList.contains("is-visible"))
41
+ return;
42
+ this.positionAtPointer(event);
43
+ };
44
+ // Show and position the tooltip above the focused element for keyboard users.
45
+ showTooltipOnFocus = (event) => {
46
+ if (!this.hasTooltipTarget)
47
+ return;
48
+ const target = event.target.closest("[data-tooltip-content]");
49
+ if (!target)
50
+ return;
51
+ this.tooltipTarget.textContent = target.dataset.tooltipContent ?? "";
52
+ this.tooltipTarget.classList.add("is-visible");
53
+ this.positionAtElement(target);
54
+ };
55
+ hideTooltip = () => {
56
+ if (!this.hasTooltipTarget)
57
+ return;
58
+ this.tooltipTarget.classList.remove("is-visible");
59
+ };
60
+ // Position the tooltip relative to the pointer cursor.
61
+ positionAtPointer(event) {
62
+ const rect = this.element.getBoundingClientRect();
63
+ const tipW = this.tooltipTarget.offsetWidth;
64
+ const tipH = this.tooltipTarget.offsetHeight;
65
+ const rawLeft = event.clientX - rect.left + 8;
66
+ const rawTop = event.clientY - rect.top - 28;
67
+ const left = Math.min(rawLeft, rect.width - tipW - 4);
68
+ const top = Math.max(rawTop, tipH + 4);
69
+ this.tooltipTarget.style.left = `${left}px`;
70
+ this.tooltipTarget.style.top = `${top}px`;
71
+ }
72
+ // Position the tooltip centred above a focused SVG element (keyboard navigation).
73
+ positionAtElement(el) {
74
+ const containerRect = this.element.getBoundingClientRect();
75
+ const elRect = el.getBoundingClientRect();
76
+ const tipW = this.tooltipTarget.offsetWidth;
77
+ const tipH = this.tooltipTarget.offsetHeight;
78
+ const rawLeft = elRect.left - containerRect.left + elRect.width / 2 - tipW / 2;
79
+ const rawTop = elRect.top - containerRect.top - tipH - 8;
80
+ const left = Math.max(4, Math.min(rawLeft, containerRect.width - tipW - 4));
81
+ const top = Math.max(4, rawTop);
82
+ this.tooltipTarget.style.left = `${left}px`;
83
+ this.tooltipTarget.style.top = `${top}px`;
84
+ }
85
+ }
86
+
87
+ export { Chart as default };
88
+ //# sourceMappingURL=chart_component_controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chart_component_controller.js","sources":["../../../../../../../app/components/midwest/chart_component/chart_component_controller.ts"],"sourcesContent":["import { Controller } from '@hotwired/stimulus'\n\nexport default class Chart extends Controller<HTMLElement> {\n static targets = ['tooltip', 'svg']\n static values = { tooltipEnabled: { type: Boolean, default: true } }\n\n declare readonly tooltipTarget: HTMLElement\n declare readonly hasTooltipTarget: boolean\n declare readonly svgTarget: SVGElement\n declare readonly hasSvgTarget: boolean\n declare tooltipEnabledValue: boolean\n\n connect (): void {\n if (this.tooltipEnabledValue && this.hasTooltipTarget) {\n this.attachListeners()\n }\n }\n\n disconnect (): void {\n if (!this.hasSvgTarget) return\n this.svgTarget.removeEventListener('pointerover', this.showTooltipOnPointer)\n this.svgTarget.removeEventListener('pointermove', this.moveTooltip)\n this.svgTarget.removeEventListener('pointerout', this.hideTooltip)\n this.svgTarget.removeEventListener('focusin', this.showTooltipOnFocus)\n this.svgTarget.removeEventListener('focusout', this.hideTooltip)\n }\n\n private attachListeners (): void {\n this.svgTarget.addEventListener('pointerover', this.showTooltipOnPointer)\n this.svgTarget.addEventListener('pointermove', this.moveTooltip)\n this.svgTarget.addEventListener('pointerout', this.hideTooltip)\n this.svgTarget.addEventListener('focusin', this.showTooltipOnFocus)\n this.svgTarget.addEventListener('focusout', this.hideTooltip)\n }\n\n // Arrow functions so `this` is stable for add/removeEventListener pairing.\n\n private showTooltipOnPointer = (event: PointerEvent): void => {\n if (!this.hasTooltipTarget) return\n const target = (event.target as SVGElement).closest('[data-tooltip-content]') as SVGElement | null\n if (!target) return\n this.tooltipTarget.textContent = target.dataset.tooltipContent ?? ''\n this.tooltipTarget.classList.add('is-visible')\n this.positionAtPointer(event)\n }\n\n // Reposition tooltip as the pointer moves within the SVG so it tracks the cursor.\n private moveTooltip = (event: PointerEvent): void => {\n if (!this.tooltipTarget.classList.contains('is-visible')) return\n this.positionAtPointer(event)\n }\n\n // Show and position the tooltip above the focused element for keyboard users.\n private showTooltipOnFocus = (event: FocusEvent): void => {\n if (!this.hasTooltipTarget) return\n const target = (event.target as SVGElement).closest('[data-tooltip-content]') as SVGElement | null\n if (!target) return\n this.tooltipTarget.textContent = target.dataset.tooltipContent ?? ''\n this.tooltipTarget.classList.add('is-visible')\n this.positionAtElement(target)\n }\n\n private hideTooltip = (): void => {\n if (!this.hasTooltipTarget) return\n this.tooltipTarget.classList.remove('is-visible')\n }\n\n // Position the tooltip relative to the pointer cursor.\n private positionAtPointer (event: PointerEvent): void {\n const rect = this.element.getBoundingClientRect()\n const tipW = this.tooltipTarget.offsetWidth\n const tipH = this.tooltipTarget.offsetHeight\n const rawLeft = event.clientX - rect.left + 8\n const rawTop = event.clientY - rect.top - 28\n const left = Math.min(rawLeft, rect.width - tipW - 4)\n const top = Math.max(rawTop, tipH + 4)\n this.tooltipTarget.style.left = `${left}px`\n this.tooltipTarget.style.top = `${top}px`\n }\n\n // Position the tooltip centred above a focused SVG element (keyboard navigation).\n private positionAtElement (el: SVGElement): void {\n const containerRect = this.element.getBoundingClientRect()\n const elRect = el.getBoundingClientRect()\n const tipW = this.tooltipTarget.offsetWidth\n const tipH = this.tooltipTarget.offsetHeight\n const rawLeft = elRect.left - containerRect.left + (elRect.width / 2) - (tipW / 2)\n const rawTop = elRect.top - containerRect.top - tipH - 8\n const left = Math.max(4, Math.min(rawLeft, containerRect.width - tipW - 4))\n const top = Math.max(4, rawTop)\n this.tooltipTarget.style.left = `${left}px`\n this.tooltipTarget.style.top = `${top}px`\n }\n}\n"],"names":[],"mappings":"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"}
@@ -50,6 +50,30 @@ declare class CountdownTimer extends Controller {
50
50
  disconnect(): void;
51
51
  }
52
52
 
53
+ declare class Chart extends Controller<HTMLElement> {
54
+ static targets: string[];
55
+ static values: {
56
+ tooltipEnabled: {
57
+ type: BooleanConstructor;
58
+ default: boolean;
59
+ };
60
+ };
61
+ readonly tooltipTarget: HTMLElement;
62
+ readonly hasTooltipTarget: boolean;
63
+ readonly svgTarget: SVGElement;
64
+ readonly hasSvgTarget: boolean;
65
+ tooltipEnabledValue: boolean;
66
+ connect(): void;
67
+ disconnect(): void;
68
+ private attachListeners;
69
+ private showTooltipOnPointer;
70
+ private moveTooltip;
71
+ private showTooltipOnFocus;
72
+ private hideTooltip;
73
+ private positionAtPointer;
74
+ private positionAtElement;
75
+ }
76
+
53
77
  declare function registerMidwestControllers(application: any): void;
54
78
 
55
- export { Banner, Card, CountdownTimer, registerMidwestControllers };
79
+ export { Banner, Card, Chart, CountdownTimer, registerMidwestControllers };
@@ -3656,6 +3656,90 @@ class AvatarGroup extends Controller {
3656
3656
  }
3657
3657
  }
3658
3658
 
3659
+ class Chart extends Controller {
3660
+ static targets = ["tooltip", "svg"];
3661
+ static values = { tooltipEnabled: { type: Boolean, default: true } };
3662
+ connect() {
3663
+ if (this.tooltipEnabledValue && this.hasTooltipTarget) {
3664
+ this.attachListeners();
3665
+ }
3666
+ }
3667
+ disconnect() {
3668
+ if (!this.hasSvgTarget)
3669
+ return;
3670
+ this.svgTarget.removeEventListener("pointerover", this.showTooltipOnPointer);
3671
+ this.svgTarget.removeEventListener("pointermove", this.moveTooltip);
3672
+ this.svgTarget.removeEventListener("pointerout", this.hideTooltip);
3673
+ this.svgTarget.removeEventListener("focusin", this.showTooltipOnFocus);
3674
+ this.svgTarget.removeEventListener("focusout", this.hideTooltip);
3675
+ }
3676
+ attachListeners() {
3677
+ this.svgTarget.addEventListener("pointerover", this.showTooltipOnPointer);
3678
+ this.svgTarget.addEventListener("pointermove", this.moveTooltip);
3679
+ this.svgTarget.addEventListener("pointerout", this.hideTooltip);
3680
+ this.svgTarget.addEventListener("focusin", this.showTooltipOnFocus);
3681
+ this.svgTarget.addEventListener("focusout", this.hideTooltip);
3682
+ }
3683
+ // Arrow functions so `this` is stable for add/removeEventListener pairing.
3684
+ showTooltipOnPointer = (event) => {
3685
+ if (!this.hasTooltipTarget)
3686
+ return;
3687
+ const target = event.target.closest("[data-tooltip-content]");
3688
+ if (!target)
3689
+ return;
3690
+ this.tooltipTarget.textContent = target.dataset.tooltipContent ?? "";
3691
+ this.tooltipTarget.classList.add("is-visible");
3692
+ this.positionAtPointer(event);
3693
+ };
3694
+ // Reposition tooltip as the pointer moves within the SVG so it tracks the cursor.
3695
+ moveTooltip = (event) => {
3696
+ if (!this.tooltipTarget.classList.contains("is-visible"))
3697
+ return;
3698
+ this.positionAtPointer(event);
3699
+ };
3700
+ // Show and position the tooltip above the focused element for keyboard users.
3701
+ showTooltipOnFocus = (event) => {
3702
+ if (!this.hasTooltipTarget)
3703
+ return;
3704
+ const target = event.target.closest("[data-tooltip-content]");
3705
+ if (!target)
3706
+ return;
3707
+ this.tooltipTarget.textContent = target.dataset.tooltipContent ?? "";
3708
+ this.tooltipTarget.classList.add("is-visible");
3709
+ this.positionAtElement(target);
3710
+ };
3711
+ hideTooltip = () => {
3712
+ if (!this.hasTooltipTarget)
3713
+ return;
3714
+ this.tooltipTarget.classList.remove("is-visible");
3715
+ };
3716
+ // Position the tooltip relative to the pointer cursor.
3717
+ positionAtPointer(event) {
3718
+ const rect = this.element.getBoundingClientRect();
3719
+ const tipW = this.tooltipTarget.offsetWidth;
3720
+ const tipH = this.tooltipTarget.offsetHeight;
3721
+ const rawLeft = event.clientX - rect.left + 8;
3722
+ const rawTop = event.clientY - rect.top - 28;
3723
+ const left = Math.min(rawLeft, rect.width - tipW - 4);
3724
+ const top = Math.max(rawTop, tipH + 4);
3725
+ this.tooltipTarget.style.left = `${left}px`;
3726
+ this.tooltipTarget.style.top = `${top}px`;
3727
+ }
3728
+ // Position the tooltip centred above a focused SVG element (keyboard navigation).
3729
+ positionAtElement(el) {
3730
+ const containerRect = this.element.getBoundingClientRect();
3731
+ const elRect = el.getBoundingClientRect();
3732
+ const tipW = this.tooltipTarget.offsetWidth;
3733
+ const tipH = this.tooltipTarget.offsetHeight;
3734
+ const rawLeft = elRect.left - containerRect.left + elRect.width / 2 - tipW / 2;
3735
+ const rawTop = elRect.top - containerRect.top - tipH - 8;
3736
+ const left = Math.max(4, Math.min(rawLeft, containerRect.width - tipW - 4));
3737
+ const top = Math.max(4, rawTop);
3738
+ this.tooltipTarget.style.left = `${left}px`;
3739
+ this.tooltipTarget.style.top = `${top}px`;
3740
+ }
3741
+ }
3742
+
3659
3743
  function registerMidwestControllers(application) {
3660
3744
  application.register("midwest-card", Card);
3661
3745
  application.register("midwest-banner", Banner);
@@ -3673,7 +3757,8 @@ function registerMidwestControllers(application) {
3673
3757
  application.register("midwest-badge", Badge);
3674
3758
  application.register("midwest-confirmation", ConfirmationController);
3675
3759
  application.register("midwest-avatar-group", AvatarGroup);
3760
+ application.register("midwest-chart", Chart);
3676
3761
  }
3677
3762
 
3678
- export { Banner, Card, CountdownTimer, registerMidwestControllers };
3763
+ export { Banner, Card, Chart, CountdownTimer, registerMidwestControllers };
3679
3764
  //# sourceMappingURL=midwest.js.map