@expressivecss/expressive 0.11.0 → 0.13.1
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/CHANGELOG.md +392 -7
- package/README.md +37 -1
- package/dist/css/expressive.css +5440 -234
- package/dist/css/expressive.css.map +1 -1
- package/dist/css/expressive.min.css +1 -1
- package/dist/css/expressive.min.css.map +1 -1
- package/dist/fonts/material-symbols-outlined.woff2 +0 -0
- package/dist/fonts/material-symbols-rounded.woff2 +0 -0
- package/dist/fonts/material-symbols-sharp.woff2 +0 -0
- package/dist/js/chunks/{chunk-AYYYWUJ4.mjs → chunk-3CLXLPYS.mjs} +17 -11
- package/dist/js/chunks/chunk-3CLXLPYS.mjs.map +7 -0
- package/dist/js/chunks/chunk-3DHK5CZU.mjs +105 -0
- package/dist/js/chunks/chunk-3DHK5CZU.mjs.map +7 -0
- package/dist/js/chunks/{chunk-IMUPRRI6.mjs → chunk-3VOK6J7U.mjs} +3 -3
- package/dist/js/chunks/chunk-4PWAPV6F.mjs +7 -0
- package/dist/js/chunks/chunk-4PWAPV6F.mjs.map +7 -0
- package/dist/js/chunks/{chunk-XFJ452AZ.mjs → chunk-55IA2XUC.mjs} +5 -6
- package/dist/js/chunks/{chunk-XFJ452AZ.mjs.map → chunk-55IA2XUC.mjs.map} +2 -2
- package/dist/js/chunks/{chunk-XDB3G6RL.mjs → chunk-6N2XAEFK.mjs} +15 -4
- package/dist/js/chunks/{chunk-XDB3G6RL.mjs.map → chunk-6N2XAEFK.mjs.map} +2 -2
- package/dist/js/chunks/{chunk-MISGHDUU.mjs → chunk-6OMRGML6.mjs} +9 -7
- package/dist/js/chunks/{chunk-MISGHDUU.mjs.map → chunk-6OMRGML6.mjs.map} +2 -2
- package/dist/js/chunks/{chunk-A3BJA7V4.mjs → chunk-6WLSDZ4O.mjs} +2 -2
- package/dist/js/chunks/chunk-CCWDV5CR.mjs +292 -0
- package/dist/js/chunks/chunk-CCWDV5CR.mjs.map +7 -0
- package/dist/js/chunks/{chunk-JODJAGFS.mjs → chunk-CKQP6P76.mjs} +31 -8
- package/dist/js/chunks/chunk-CKQP6P76.mjs.map +7 -0
- package/dist/js/chunks/{chunk-KR44BSYQ.mjs → chunk-DLWYKFEI.mjs} +3 -3
- package/dist/js/chunks/chunk-DTKR54I6.mjs +270 -0
- package/dist/js/chunks/chunk-DTKR54I6.mjs.map +7 -0
- package/dist/js/chunks/{chunk-SLFNPY5M.mjs → chunk-EC63CHXU.mjs} +2 -2
- package/dist/js/chunks/chunk-GVGT6MIU.mjs +47 -0
- package/dist/js/chunks/chunk-GVGT6MIU.mjs.map +7 -0
- package/dist/js/chunks/{chunk-LZVBJ33S.mjs → chunk-GZWPXXY6.mjs} +15 -8
- package/dist/js/chunks/chunk-GZWPXXY6.mjs.map +7 -0
- package/dist/js/chunks/chunk-HKT2S7VM.mjs +48 -0
- package/dist/js/chunks/chunk-HKT2S7VM.mjs.map +7 -0
- package/dist/js/chunks/{chunk-D4UZ4HFN.mjs → chunk-IFXVDDDH.mjs} +23 -11
- package/dist/js/chunks/chunk-IFXVDDDH.mjs.map +7 -0
- package/dist/js/chunks/chunk-K4CJCRGE.mjs +262 -0
- package/dist/js/chunks/chunk-K4CJCRGE.mjs.map +7 -0
- package/dist/js/chunks/chunk-LNCCYGPC.mjs +163 -0
- package/dist/js/chunks/chunk-LNCCYGPC.mjs.map +7 -0
- package/dist/js/chunks/{chunk-QSQ24FYT.mjs → chunk-LTWPGFBR.mjs} +2 -2
- package/dist/js/chunks/{chunk-QSQ24FYT.mjs.map → chunk-LTWPGFBR.mjs.map} +2 -2
- package/dist/js/chunks/{chunk-I5KR22BY.mjs → chunk-LWBQIX5J.mjs} +15 -15
- package/dist/js/chunks/chunk-LWBQIX5J.mjs.map +7 -0
- package/dist/js/chunks/{chunk-GY2Z5CJ2.mjs → chunk-NNYP33NB.mjs} +67 -32
- package/dist/js/chunks/chunk-NNYP33NB.mjs.map +7 -0
- package/dist/js/chunks/chunk-NQLC3YMW.mjs +1 -0
- package/dist/js/chunks/chunk-O5XPWXIQ.mjs +406 -0
- package/dist/js/chunks/chunk-O5XPWXIQ.mjs.map +7 -0
- package/dist/js/chunks/chunk-P3G3QHII.mjs +166 -0
- package/dist/js/chunks/chunk-P3G3QHII.mjs.map +7 -0
- package/dist/js/chunks/{chunk-VAS6JQ6P.mjs → chunk-PIJ2TAR3.mjs} +3 -3
- package/dist/js/chunks/{chunk-74N6U5JJ.mjs → chunk-PLYXLSH3.mjs} +38 -37
- package/dist/js/chunks/chunk-PLYXLSH3.mjs.map +7 -0
- package/dist/js/chunks/{chunk-PIIAEYAJ.mjs → chunk-QDAL4IYN.mjs} +2 -2
- package/dist/js/chunks/chunk-QKWPQK5N.mjs +179 -0
- package/dist/js/chunks/chunk-QKWPQK5N.mjs.map +7 -0
- package/dist/js/chunks/{chunk-FRB7TOCS.mjs → chunk-QV2JAWIZ.mjs} +2 -2
- package/dist/js/chunks/{chunk-N3UHGN3N.mjs → chunk-QVVEWBOF.mjs} +3 -3
- package/dist/js/chunks/chunk-RHRQKTTX.mjs +139 -0
- package/dist/js/chunks/chunk-RHRQKTTX.mjs.map +7 -0
- package/dist/js/chunks/chunk-SPETGK25.mjs +59 -0
- package/dist/js/chunks/chunk-SPETGK25.mjs.map +7 -0
- package/dist/js/chunks/{chunk-TK6PX2GC.mjs → chunk-U2OTHOTI.mjs} +131 -19
- package/dist/js/chunks/chunk-U2OTHOTI.mjs.map +7 -0
- package/dist/js/chunks/{chunk-TYM6U5DY.mjs → chunk-UAEAQBRC.mjs} +2 -2
- package/dist/js/chunks/{chunk-7UXHSYIA.mjs → chunk-UBLRRJ7N.mjs} +3 -3
- package/dist/js/chunks/{chunk-EP3CVKB5.mjs → chunk-UEZUJQ66.mjs} +8 -5
- package/dist/js/chunks/chunk-UEZUJQ66.mjs.map +7 -0
- package/dist/js/chunks/{chunk-JNPIWFJT.mjs → chunk-UNEMYWEW.mjs} +3 -3
- package/dist/js/chunks/chunk-VTLBW7QS.mjs +124 -0
- package/dist/js/chunks/chunk-VTLBW7QS.mjs.map +7 -0
- package/dist/js/chunks/{chunk-JKNPQQWY.mjs → chunk-WJXDBPXQ.mjs} +28 -12
- package/dist/js/chunks/chunk-WJXDBPXQ.mjs.map +7 -0
- package/dist/js/chunks/{chunk-CDW6WIRT.mjs → chunk-XGHORT7J.mjs} +18 -11
- package/dist/js/chunks/chunk-XGHORT7J.mjs.map +7 -0
- package/dist/js/chunks/{chunk-7GKXUG4B.mjs → chunk-XH6BEEMY.mjs} +78 -25
- package/dist/js/chunks/chunk-XH6BEEMY.mjs.map +7 -0
- package/dist/js/chunks/{chunk-XO5WX3TK.mjs → chunk-YDCS5S3J.mjs} +2 -2
- package/dist/js/expressive.cjs +2540 -233
- package/dist/js/expressive.cjs.map +4 -4
- package/dist/js/expressive.js +2540 -233
- package/dist/js/expressive.js.map +4 -4
- package/dist/js/expressive.min.js +10 -10
- package/dist/js/expressive.min.js.map +4 -4
- package/dist/js/expressive.mjs +86 -38
- package/dist/js/expressive.mjs.map +1 -1
- package/dist/js/internal/behaviors/bottomSheets.mjs +3 -3
- package/dist/js/internal/behaviors/dialogs.mjs +2 -2
- package/dist/js/internal/behaviors/forms.mjs +2 -2
- package/dist/js/internal/behaviors/sheetDrag.mjs +2 -2
- package/dist/js/internal/behaviors/sideSheets.mjs +3 -3
- package/dist/js/internal/components/appBar.mjs +2 -2
- package/dist/js/internal/components/autocomplete.mjs +4 -4
- package/dist/js/internal/components/barChart.mjs +10 -0
- package/dist/js/internal/components/barChart.mjs.map +7 -0
- package/dist/js/internal/components/buttonGroup.mjs +2 -2
- package/dist/js/internal/components/buttons.mjs +3 -3
- package/dist/js/internal/components/cards.mjs +3 -3
- package/dist/js/internal/components/carousel.mjs +3 -3
- package/dist/js/internal/components/characterCounter.mjs +2 -2
- package/dist/js/internal/components/chips.mjs +5 -5
- package/dist/js/internal/components/columnChart.mjs +9 -0
- package/dist/js/internal/components/columnChart.mjs.map +7 -0
- package/dist/js/internal/components/commandPalette.mjs +9 -0
- package/dist/js/internal/components/commandPalette.mjs.map +7 -0
- package/dist/js/internal/components/datepicker.mjs +6 -6
- package/dist/js/internal/components/expandingCard.mjs +3 -3
- package/dist/js/internal/components/heatmapChart.mjs +9 -0
- package/dist/js/internal/components/heatmapChart.mjs.map +7 -0
- package/dist/js/internal/components/index.mjs +79 -31
- package/dist/js/internal/components/lightbox.mjs +3 -3
- package/dist/js/internal/components/lineChart.mjs +12 -0
- package/dist/js/internal/components/lineChart.mjs.map +7 -0
- package/dist/js/internal/components/menu.mjs +3 -3
- package/dist/js/internal/components/messageScroller.mjs +9 -0
- package/dist/js/internal/components/messageScroller.mjs.map +7 -0
- package/dist/js/internal/components/mixedChart.mjs +10 -0
- package/dist/js/internal/components/mixedChart.mjs.map +7 -0
- package/dist/js/internal/components/navigationRail.mjs +2 -2
- package/dist/js/internal/components/pieChart.mjs +9 -0
- package/dist/js/internal/components/pieChart.mjs.map +7 -0
- package/dist/js/internal/components/questionnaire.mjs +9 -0
- package/dist/js/internal/components/questionnaire.mjs.map +7 -0
- package/dist/js/internal/components/radarChart.mjs +9 -0
- package/dist/js/internal/components/radarChart.mjs.map +7 -0
- package/dist/js/internal/components/radialChart.mjs +9 -0
- package/dist/js/internal/components/radialChart.mjs.map +7 -0
- package/dist/js/internal/components/registry.mjs +37 -25
- package/dist/js/internal/components/richTextEditor.mjs +9 -0
- package/dist/js/internal/components/richTextEditor.mjs.map +7 -0
- package/dist/js/internal/components/scrollspy.mjs +2 -2
- package/dist/js/internal/components/select.mjs +4 -4
- package/dist/js/internal/components/slider.mjs +3 -3
- package/dist/js/internal/components/snackbar.mjs +2 -2
- package/dist/js/internal/components/tabs.mjs +4 -4
- package/dist/js/internal/components/timepicker.mjs +4 -4
- package/dist/js/internal/components/tooltip.mjs +3 -3
- package/dist/js/internal/core/component.mjs +1 -1
- package/dist/js/internal/core/utils.mjs +1 -1
- package/dist/js/internal/plugins/dockedDisplayPlugin.mjs +2 -2
- package/dist/js/modular.mjs +86 -38
- package/dist/types/behaviors/forms.d.ts +22 -0
- package/dist/types/components/appBar.d.ts +1 -1
- package/dist/types/components/barChart.d.ts +24 -0
- package/dist/types/components/columnChart.d.ts +21 -0
- package/dist/types/components/commandPalette.d.ts +96 -0
- package/dist/types/components/datepicker.d.ts +5 -2
- package/dist/types/components/heatmapChart.d.ts +49 -0
- package/dist/types/components/index.d.ts +12 -0
- package/dist/types/components/lineChart.d.ts +134 -0
- package/dist/types/components/menu.d.ts +32 -0
- package/dist/types/components/messageScroller.d.ts +111 -0
- package/dist/types/components/mixedChart.d.ts +25 -0
- package/dist/types/components/pieChart.d.ts +40 -0
- package/dist/types/components/questionnaire.d.ts +96 -0
- package/dist/types/components/radarChart.d.ts +39 -0
- package/dist/types/components/radialChart.d.ts +45 -0
- package/dist/types/components/registry.d.ts +44 -0
- package/dist/types/components/richTextEditor.d.ts +71 -0
- package/dist/types/components/slider.d.ts +1 -0
- package/dist/types/components/snackbar.d.ts +6 -0
- package/dist/types/components/timepicker.d.ts +4 -1
- package/dist/types/components/tooltip.d.ts +2 -1
- package/dist/types/modular.d.ts +10 -1
- package/package.json +4 -1
- package/src/sass/README.md +3 -6
- package/src/sass/abstracts/_index.scss +1 -1
- package/src/sass/abstracts/_mixins.scss +226 -0
- package/src/sass/abstracts/_variables.scss +14 -0
- package/src/sass/base/_typography.scss +45 -0
- package/src/sass/components/_accordion.scss +161 -0
- package/src/sass/components/_aura.scss +119 -0
- package/src/sass/components/_avatar.scss +86 -0
- package/src/sass/components/_bar-chart.scss +285 -0
- package/src/sass/components/_bottom-sheet.scss +1 -0
- package/src/sass/components/_button-groups.scss +13 -3
- package/src/sass/components/_cards.scss +16 -13
- package/src/sass/components/_carousel.scss +9 -7
- package/src/sass/components/_column-chart.scss +134 -0
- package/src/sass/components/_command-palette.scss +140 -0
- package/src/sass/components/_countdown.scss +89 -0
- package/src/sass/components/_data-table.scss +188 -0
- package/src/sass/components/_dialog.scss +1 -0
- package/src/sass/components/_empty-state.scss +78 -0
- package/src/sass/components/_expanding-card.scss +3 -0
- package/src/sass/components/_heatmap-chart.scss +156 -0
- package/src/sass/components/_index.scss +27 -0
- package/src/sass/components/_kpi.scss +162 -0
- package/src/sass/components/_line-chart.scss +102 -0
- package/src/sass/components/_marquee.scss +111 -0
- package/src/sass/components/_menu.scss +10 -0
- package/src/sass/components/_message-scroller.scss +66 -0
- package/src/sass/components/_message.scss +202 -0
- package/src/sass/components/_mixed-chart.scss +157 -0
- package/src/sass/components/_navbar.scss +11 -6
- package/src/sass/components/_navigation-bar.scss +1 -0
- package/src/sass/components/_navigation-rail.scss +9 -0
- package/src/sass/components/_page-footer.scss +0 -11
- package/src/sass/components/_pie-chart.scss +203 -0
- package/src/sass/components/_popover.scss +112 -0
- package/src/sass/components/_progress.scss +25 -6
- package/src/sass/components/_questionnaire.scss +144 -0
- package/src/sass/components/_radar-chart.scss +205 -0
- package/src/sass/components/_radial-chart.scss +174 -0
- package/src/sass/components/_rich-text-editor.scss +99 -0
- package/src/sass/components/_search.scss +1 -0
- package/src/sass/components/_side-sheet.scss +1 -0
- package/src/sass/components/_skeleton.scss +81 -0
- package/src/sass/components/_snackbar.scss +2 -1
- package/src/sass/components/_stat.scss +86 -0
- package/src/sass/components/_stepper.scss +190 -0
- package/src/sass/components/_timeline.scss +114 -0
- package/src/sass/components/_timepicker.scss +2 -2
- package/src/sass/components/_toolbar.scss +2 -1
- package/src/sass/components/_tooltip.scss +2 -0
- package/src/sass/components/_tree.scss +139 -0
- package/src/sass/components/forms/_checkboxes.scss +2 -2
- package/src/sass/components/forms/_drop-zone.scss +128 -0
- package/src/sass/components/forms/_index.scss +2 -0
- package/src/sass/components/forms/_input-fields.scss +166 -15
- package/src/sass/components/forms/_radio-buttons.scss +2 -2
- package/src/sass/components/forms/_rating.scss +165 -0
- package/src/sass/components/forms/_slider.scss +51 -29
- package/src/sass/components/forms/_switches.scss +3 -3
- package/src/sass/tokens/_reference.scss +3 -15
- package/src/sass/utilities/_helpers.scss +14 -0
- package/src/sass/utilities/_index.scss +2 -0
- package/src/sass/utilities/_scroll-area.scss +35 -0
- package/src/sass/utilities/_shapes.scss +164 -0
- package/src/sass/utilities/_spacing.scss +29 -23
- package/src/sass/utilities/_visibility.scss +3 -2
- package/dist/js/chunks/chunk-74N6U5JJ.mjs.map +0 -7
- package/dist/js/chunks/chunk-7GKXUG4B.mjs.map +0 -7
- package/dist/js/chunks/chunk-AYYYWUJ4.mjs.map +0 -7
- package/dist/js/chunks/chunk-CDW6WIRT.mjs.map +0 -7
- package/dist/js/chunks/chunk-D4UZ4HFN.mjs.map +0 -7
- package/dist/js/chunks/chunk-EP3CVKB5.mjs.map +0 -7
- package/dist/js/chunks/chunk-GY2Z5CJ2.mjs.map +0 -7
- package/dist/js/chunks/chunk-I5KR22BY.mjs.map +0 -7
- package/dist/js/chunks/chunk-JKNPQQWY.mjs.map +0 -7
- package/dist/js/chunks/chunk-JODJAGFS.mjs.map +0 -7
- package/dist/js/chunks/chunk-JR24UB4X.mjs +0 -100
- package/dist/js/chunks/chunk-JR24UB4X.mjs.map +0 -7
- package/dist/js/chunks/chunk-LZVBJ33S.mjs.map +0 -7
- package/dist/js/chunks/chunk-PMBPAFAS.mjs +0 -7
- package/dist/js/chunks/chunk-PMBPAFAS.mjs.map +0 -7
- package/dist/js/chunks/chunk-TK6PX2GC.mjs.map +0 -7
- package/dist/js/chunks/chunk-WWPAPHMA.mjs +0 -1
- /package/dist/js/chunks/{chunk-IMUPRRI6.mjs.map → chunk-3VOK6J7U.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-A3BJA7V4.mjs.map → chunk-6WLSDZ4O.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-KR44BSYQ.mjs.map → chunk-DLWYKFEI.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-SLFNPY5M.mjs.map → chunk-EC63CHXU.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-WWPAPHMA.mjs.map → chunk-NQLC3YMW.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-VAS6JQ6P.mjs.map → chunk-PIJ2TAR3.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-PIIAEYAJ.mjs.map → chunk-QDAL4IYN.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-FRB7TOCS.mjs.map → chunk-QV2JAWIZ.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-N3UHGN3N.mjs.map → chunk-QVVEWBOF.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-TYM6U5DY.mjs.map → chunk-UAEAQBRC.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-7UXHSYIA.mjs.map → chunk-UBLRRJ7N.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-JNPIWFJT.mjs.map → chunk-UNEMYWEW.mjs.map} +0 -0
- /package/dist/js/chunks/{chunk-XO5WX3TK.mjs.map → chunk-YDCS5S3J.mjs.map} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/behaviors/forms.ts"],
|
|
4
|
+
"sourcesContent": ["import { Utils } from '../core/utils';\n\nexport class Forms {\n /**\n * Checks if the label has validation and apply\n * the correct class and styles\n * @param textfield\n */\n static validateField(textfield: HTMLInputElement) {\n if (!textfield) {\n console.error('No text field element found');\n return;\n }\n\n const hasLength = textfield.getAttribute('data-length') !== null;\n const lenAttr = parseInt(textfield.getAttribute('data-length'));\n const len = textfield.value.length;\n\n if (\n len === 0 &&\n textfield.validity.badInput === false &&\n !textfield.required &&\n textfield.classList.contains('validate')\n ) {\n textfield.classList.remove('invalid');\n } else if (textfield.classList.contains('validate')) {\n // Check for character counter attributes\n if (\n (textfield.validity.valid && hasLength && len <= lenAttr) ||\n (textfield.validity.valid && !hasLength)\n ) {\n textfield.classList.remove('invalid');\n } else {\n textfield.classList.add('invalid');\n }\n }\n }\n\n /**\n * Resizes the given TextArea after updating the\n * value content dynamically.\n * @param e EventTarget\n */\n static textareaAutoResize(e: EventTarget) {\n const textarea = e as HTMLTextAreaElement;\n if (!textarea) return;\n\n // Measure the textarea against itself: collapse it to its natural height,\n // then read the content height back. `.expressive-textarea` is\n // `overflow-y: hidden`, so scrollHeight is the full content height and\n // offsetHeight - clientHeight is exactly the borders (no scrollbar to\n // account for) - which border-box sizing needs added back.\n //\n // This replaces a mirror div that the value was copied into via\n // `innerHTML = innerHTML.replace(...)` - a full serialize and reparse of\n // the text on every keystroke, plus getComputedStyle and seven style\n // writes, run twice per keystroke because it was bound to keydown and\n // keyup both.\n if (!textarea.hasAttribute('original-height')) {\n textarea.setAttribute('original-height', textarea.getBoundingClientRect().height.toString());\n }\n const originalHeight = parseInt(textarea.getAttribute('original-height'));\n if (isNaN(originalHeight)) return;\n\n textarea.style.height = 'auto';\n // Three reads after a single write: one layout flush for the whole resize.\n const borders = textarea.offsetHeight - textarea.clientHeight;\n const contentHeight = textarea.scrollHeight + borders;\n textarea.style.height = Math.max(originalHeight, contentHeight) + 'px';\n }\n\n static Init() {\n Utils.onDocumentReady(() => {\n document.addEventListener('change', (e: KeyboardEvent) => {\n const target = <HTMLInputElement>e.target;\n if (target instanceof HTMLInputElement && target.type === 'file') {\n const zone = target.closest('.drop-zone');\n if (zone) Forms.listDropZoneFiles(zone, target);\n }\n if (target instanceof HTMLInputElement) {\n // The sibling-label loop that used to live here compared\n // `tagName == 'label'` (tagName is uppercase) so it never matched,\n // and no rule in the Sass styles `label.active` anyway - the\n // floating label is driven by CSS, not by a class from here.\n Forms.validateField(target);\n }\n });\n\n document.addEventListener('keyup', (e: KeyboardEvent) => {\n const target = <HTMLInputElement>e.target;\n // Radio and Checkbox focus class\n if (target instanceof HTMLInputElement && ['radio', 'checkbox'].includes(target.type)) {\n // TAB, check if tabbing to radio or checkbox.\n if (e.key === Utils.keys.TAB) {\n target.classList.add('tabbed');\n target.addEventListener('blur', () => target.classList.remove('tabbed'), {\n once: true\n });\n }\n }\n });\n\n document.addEventListener('click', Forms.togglePassword);\n // Capture, so the password is hidden again before any submit handler\n // reads the form or the browser offers to save it.\n document.addEventListener('submit', Forms.resetFormExtras, true);\n document.addEventListener('reset', Forms.resetFormExtras, true);\n for (const type of ['dragenter', 'dragover', 'dragleave', 'drop']) {\n document.addEventListener(type, Forms.markDropZone);\n }\n\n document.querySelectorAll('.expressive-textarea').forEach((textArea: HTMLTextAreaElement) => {\n Forms.InitTextarea(textArea);\n });\n\n // File Input Path\n document\n .querySelectorAll('.file-field input[type=\"file\"]')\n .forEach((fileInput: HTMLInputElement) => {\n Forms.InitFileInputPath(fileInput);\n });\n });\n }\n\n /**\n * A .password-toggle button shows or hides the password in its field. The\n * button's own name stays put (\"Show password\"); aria-pressed carries the\n * state, so there is no generated text to translate.\n */\n static togglePassword(e: MouseEvent) {\n const button = (<Element>e.target).closest?.('.password-toggle');\n const input = button?.closest('.field')?.querySelector<HTMLInputElement>(\n 'input[type=\"password\"], input[data-password]'\n );\n if (!input) return;\n const show = input.type === 'password';\n // Marked so the input is still found once it has become type=\"text\".\n input.toggleAttribute('data-password', show);\n input.type = show ? 'text' : 'password';\n button.setAttribute('aria-pressed', String(show));\n }\n\n /**\n * A revealed password goes back to type=\"password\" when its form is\n * submitted or reset, so it is never sent or autofilled as plain text and\n * a reset field does not stay revealed. A reset form also drops the file\n * lists it would otherwise leave showing: reset fires no change event.\n */\n static resetFormExtras(e: Event) {\n const form = e.target;\n if (!(form instanceof HTMLFormElement)) return;\n form.querySelectorAll<HTMLInputElement>('input[data-password]').forEach((input) => {\n input.removeAttribute('data-password');\n input.type = 'password';\n input.closest('.field')?.querySelector('.password-toggle')?.setAttribute('aria-pressed', 'false');\n });\n if (e.type === 'reset') {\n form.querySelectorAll('.drop-zone-files').forEach((list) => list.replaceChildren());\n form.querySelectorAll('.drop-zone.dragover').forEach((zone) => zone.classList.remove('dragover'));\n }\n }\n\n /**\n * The native file input covers its .drop-zone, so the browser already takes\n * a dropped file. This only shows the drag: the input is the topmost\n * element, so every drag event over the zone targets it and leaving it is\n * leaving the zone.\n */\n static markDropZone(e: DragEvent) {\n const input = <Element>e.target;\n if (!(input instanceof HTMLInputElement) || input.type !== 'file') return;\n const zone = input.closest('.drop-zone');\n if (!zone) return;\n const over = e.type === 'dragenter' || e.type === 'dragover';\n zone.classList.toggle('dragover', over && !input.disabled);\n }\n\n /** Lists the chosen files, name and size, in the zone's .drop-zone-files. */\n static listDropZoneFiles(zone: Element, input: HTMLInputElement) {\n const list = zone.querySelector('.drop-zone-files');\n if (!list) return;\n const size = (bytes: number) => {\n const [value, unit] =\n bytes >= 1e6 ? [bytes / 1e6, 'megabyte'] : bytes >= 1e3 ? [bytes / 1e3, 'kilobyte'] : [bytes, 'byte'];\n return new Intl.NumberFormat(undefined, { style: 'unit', unit, maximumFractionDigits: 1 }).format(value);\n };\n list.replaceChildren(\n ...Array.from(input.files ?? [], (file) => {\n const item = document.createElement('li');\n const name = document.createElement('span');\n const meta = document.createElement('span');\n name.textContent = file.name;\n meta.textContent = size(file.size);\n item.append(name, meta);\n return item;\n })\n );\n }\n\n static InitTextarea(textarea: HTMLTextAreaElement) {\n // Save Data in Element\n textarea.setAttribute('original-height', textarea.getBoundingClientRect().height.toString());\n Forms.textareaAutoResize(textarea);\n // `input` rather than keydown + keyup: it fires once per actual value\n // change and also covers paste, drag-drop and IME composition, which the\n // key events missed.\n textarea.addEventListener('input', (e) => Forms.textareaAutoResize(e.target));\n }\n\n static InitFileInputPath(fileInput: HTMLInputElement) {\n fileInput.addEventListener('change', () => {\n const fileField = fileInput.closest('.file-field');\n const pathInput = <HTMLInputElement>fileField.querySelector('input.file-path');\n const files = fileInput.files;\n const filenames = [];\n for (let i = 0; i < files.length; i++) {\n filenames.push(files[i].name);\n }\n pathInput.value = filenames.join(', ');\n pathInput.dispatchEvent(\n new Event('change', { bubbles: true, cancelable: true, composed: true })\n );\n });\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Component
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LTWPGFBR.mjs";
|
|
4
4
|
|
|
5
5
|
// src/ts/components/scrollspy.ts
|
|
6
6
|
var _defaultGetActiveElement = (id) => `a[href="#${id}"]`;
|
|
@@ -132,4 +132,4 @@ var ScrollSpy = _ScrollSpy;
|
|
|
132
132
|
export {
|
|
133
133
|
ScrollSpy
|
|
134
134
|
};
|
|
135
|
-
//# sourceMappingURL=chunk-
|
|
135
|
+
//# sourceMappingURL=chunk-QV2JAWIZ.mjs.map
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Utils
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6OMRGML6.mjs";
|
|
4
4
|
import {
|
|
5
5
|
Component
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LTWPGFBR.mjs";
|
|
7
7
|
|
|
8
8
|
// src/ts/components/expandingCard.ts
|
|
9
9
|
var _defaults = {
|
|
@@ -172,4 +172,4 @@ export {
|
|
|
172
172
|
EXPANDING_CARD_SELECTOR,
|
|
173
173
|
ExpandingCard
|
|
174
174
|
};
|
|
175
|
-
//# sourceMappingURL=chunk-
|
|
175
|
+
//# sourceMappingURL=chunk-QVVEWBOF.mjs.map
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
COLORS,
|
|
3
|
+
LineChart,
|
|
4
|
+
svgNode
|
|
5
|
+
} from "./chunk-O5XPWXIQ.mjs";
|
|
6
|
+
|
|
7
|
+
// src/ts/components/radialChart.ts
|
|
8
|
+
var RADIUS = 46;
|
|
9
|
+
var FILL = 0.8;
|
|
10
|
+
var RadialChart = class extends LineChart {
|
|
11
|
+
get _type() {
|
|
12
|
+
return "radial-chart";
|
|
13
|
+
}
|
|
14
|
+
get _key() {
|
|
15
|
+
return "Expressive_RadialChart";
|
|
16
|
+
}
|
|
17
|
+
get _points() {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
get _circular() {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
get _gauge() {
|
|
24
|
+
return this.el.classList.contains("gauge");
|
|
25
|
+
}
|
|
26
|
+
static init(els, options = {}) {
|
|
27
|
+
return super.init(els, options);
|
|
28
|
+
}
|
|
29
|
+
static getInstance(el) {
|
|
30
|
+
return el["Expressive_RadialChart"];
|
|
31
|
+
}
|
|
32
|
+
show(index) {
|
|
33
|
+
if (!this._tooltip || index === this.activeIndex) return;
|
|
34
|
+
super.show(index);
|
|
35
|
+
this._rings.forEach((ring, i) => ring.classList.toggle("active", i === index));
|
|
36
|
+
if (this._tooltip.hidden) return;
|
|
37
|
+
const color = this._color(index);
|
|
38
|
+
this._tooltip.querySelectorAll("[data-series]").forEach((span) => {
|
|
39
|
+
span.dataset.series = color;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/** The tooltip sits where the ring's fill ends. */
|
|
43
|
+
_place(index) {
|
|
44
|
+
const turn = this._turn(this._fractions[index]);
|
|
45
|
+
const r = this._radii[index];
|
|
46
|
+
const [x, y] = [r * Math.sin(turn * 2 * Math.PI), -r * Math.cos(turn * 2 * Math.PI)];
|
|
47
|
+
this._tooltip.style.left = `${50 + x}%`;
|
|
48
|
+
this._tooltip.style.top = `${(50 + y) / (this._gauge ? 50 : 100) * 100}%`;
|
|
49
|
+
this._tooltip.classList.toggle("end", x > 0);
|
|
50
|
+
}
|
|
51
|
+
_color(index) {
|
|
52
|
+
return String(index % COLORS + 1);
|
|
53
|
+
}
|
|
54
|
+
/** A fraction of the ring as a turn clockwise from the top. */
|
|
55
|
+
_turn(fraction) {
|
|
56
|
+
return this._gauge ? fraction / 2 - 0.25 : fraction;
|
|
57
|
+
}
|
|
58
|
+
/** For more than one row, a legend of every row with its color and cell. */
|
|
59
|
+
_guides() {
|
|
60
|
+
if (this.labels.length < 2) return [];
|
|
61
|
+
const legend = document.createElement("ul");
|
|
62
|
+
legend.className = "radial-chart-legend";
|
|
63
|
+
legend.setAttribute("aria-hidden", "true");
|
|
64
|
+
const text = this.series[0].text;
|
|
65
|
+
legend.append(...this.labels.map((label, i) => {
|
|
66
|
+
const li = document.createElement("li");
|
|
67
|
+
li.dataset.series = this._color(i);
|
|
68
|
+
const [name, value] = [label, text[i]].map((content) => {
|
|
69
|
+
const span = document.createElement("span");
|
|
70
|
+
span.textContent = content;
|
|
71
|
+
return span;
|
|
72
|
+
});
|
|
73
|
+
li.append(name, value);
|
|
74
|
+
return li;
|
|
75
|
+
}));
|
|
76
|
+
return [legend];
|
|
77
|
+
}
|
|
78
|
+
/** The ring under the pointer by its distance from the middle, or -1. */
|
|
79
|
+
_indexAt(e) {
|
|
80
|
+
const box = this._plot.getBoundingClientRect();
|
|
81
|
+
const [x, y] = [e.clientX - box.left - box.width / 2, e.clientY - box.top - box.width / 2];
|
|
82
|
+
if (this._gauge && y > 0) return -1;
|
|
83
|
+
const distance = Math.hypot(x, y) / box.width * 100;
|
|
84
|
+
const step = this._radii.length > 1 ? this._radii[0] - this._radii[1] : this._width;
|
|
85
|
+
return this._radii.findIndex((r) => Math.abs(distance - r) <= step / 2);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* An SVG of rings in a -50 to 50 box, the top half for a gauge. Each row
|
|
89
|
+
* is a track circle and a fill circle whose dash is its share; CSS draws
|
|
90
|
+
* them from --radial-chart-dash. The total is HTML over it.
|
|
91
|
+
*/
|
|
92
|
+
_draw() {
|
|
93
|
+
const style = getComputedStyle(this.el);
|
|
94
|
+
const token = (name, fallback) => {
|
|
95
|
+
const value = parseFloat(style.getPropertyValue(`--md-comp-radial-chart-${name}`));
|
|
96
|
+
return Number.isFinite(value) ? value : fallback;
|
|
97
|
+
};
|
|
98
|
+
const count = this.labels.length;
|
|
99
|
+
let [width, gap] = [Math.max(0, token("thickness", 8)), Math.max(0, token("gap", 2))];
|
|
100
|
+
const scale = Math.min(1, RADIUS * FILL / (count * width + (count - 1) * gap || 1));
|
|
101
|
+
[width, gap] = [width * scale, gap * scale];
|
|
102
|
+
this._width = width;
|
|
103
|
+
this._radii = this.labels.map((_, i) => RADIUS - width / 2 - i * (width + gap));
|
|
104
|
+
const max = [parseFloat(this.el.dataset.max ?? ""), this.options.max ?? NaN, 100].find((value) => value > 0);
|
|
105
|
+
this._fractions = this.series[0].values.map((value) => Math.min(1, Math.max(0, (value ?? 0) / max)));
|
|
106
|
+
const gauge = this._gauge;
|
|
107
|
+
const svg = svgNode("svg", { viewBox: gauge ? "-50 -50 100 50" : "-50 -50 100 100", focusable: "false" });
|
|
108
|
+
const transform = gauge ? "rotate(180)" : "rotate(-90)";
|
|
109
|
+
const span = gauge ? 0.5 : 1;
|
|
110
|
+
this._rings = this._radii.map((r, i) => {
|
|
111
|
+
const length = 2 * Math.PI * r;
|
|
112
|
+
const circle = (name, fraction, capped) => {
|
|
113
|
+
const ring2 = svgNode("circle", { class: name, r: r.toFixed(3), transform, "stroke-width": width.toFixed(3) });
|
|
114
|
+
const dash = Math.max(1e-3, fraction * span * length - (capped ? width : 0));
|
|
115
|
+
ring2.style.setProperty("--radial-chart-dash", `${dash.toFixed(3)} ${length.toFixed(3)}`);
|
|
116
|
+
if (capped) ring2.style.setProperty("--radial-chart-offset", (-width / 2).toFixed(3));
|
|
117
|
+
return ring2;
|
|
118
|
+
};
|
|
119
|
+
const ring = circle("radial-chart-ring", this._fractions[i], true);
|
|
120
|
+
ring.dataset.series = this._color(i);
|
|
121
|
+
if (!this._fractions[i]) ring.classList.add("empty");
|
|
122
|
+
svg.append(circle("radial-chart-track", 1, gauge), ring);
|
|
123
|
+
return ring;
|
|
124
|
+
});
|
|
125
|
+
const rings = document.createElement("div");
|
|
126
|
+
rings.className = "radial-chart-rings";
|
|
127
|
+
rings.setAttribute("aria-hidden", "true");
|
|
128
|
+
rings.style.setProperty("--radial-chart-middle", `${(this._radii[count - 1] - this._width / 2) * 2}%`);
|
|
129
|
+
rings.append(svg);
|
|
130
|
+
const total = this._total("radial-chart-total");
|
|
131
|
+
if (total) rings.append(total);
|
|
132
|
+
return rings;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export {
|
|
137
|
+
RadialChart
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=chunk-RHRQKTTX.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/radialChart.ts"],
|
|
4
|
+
"sourcesContent": ["import { InitElements, InitElement } from '../core/component';\nimport { COLORS, LineChart, LineChartOptions, svgNode as node } from './lineChart';\n\nexport type RadialChartOptions = LineChartOptions;\n\n/** The outer ring's outer edge in a 100-unit box. */\nconst RADIUS = 46;\n/** The rings never fill more of the radius than this, leaving a middle. */\nconst FILL = 0.8;\n\n/**\n * Radial chart. It reads its <table> like LineChart, but draws each row of\n * the first value column as a ring, outermost first, filled clockwise from\n * the top as a share of `data-max` above zero (100 by default). With `.gauge` the rings\n * are half circles over the middle. A <tfoot> row shows in the middle, and\n * a legend lists the rows when there is more than one. Further columns show\n * in the tooltip.\n *\n * Re-run `RadialChart.init(el)` after changing the table or the ring tokens.\n */\nexport class RadialChart extends LineChart {\n // No initializers: LineChart's constructor draws before they would run.\n /** Each ring's middle radius, and their shared width. */\n private _radii: number[];\n private _width: number;\n /** Each row's share of the maximum, from 0 to 1. */\n private _fractions: number[];\n private _rings: SVGCircleElement[];\n\n protected get _type() {\n return 'radial-chart';\n }\n\n protected get _key() {\n return 'Expressive_RadialChart';\n }\n\n protected get _points() {\n return false;\n }\n\n protected get _circular() {\n return true;\n }\n\n private get _gauge() {\n return this.el.classList.contains('gauge');\n }\n\n static init(el: HTMLElement, options?: Partial<RadialChartOptions>): RadialChart;\n static init(els: InitElements<InitElement>, options?: Partial<RadialChartOptions>): RadialChart[];\n static init(\n els: HTMLElement | InitElements<InitElement>,\n options: Partial<RadialChartOptions> = {}\n ): RadialChart | RadialChart[] {\n return super.init(els as HTMLElement, options) as RadialChart | RadialChart[];\n }\n\n static getInstance(el: HTMLElement): RadialChart {\n return el['Expressive_RadialChart'];\n }\n\n show(index: number) {\n if (!this._tooltip || index === this.activeIndex) return;\n super.show(index);\n this._rings.forEach((ring, i) => ring.classList.toggle('active', i === index));\n // LineChart hides the tooltip for -1 and for an index past the last row.\n if (this._tooltip.hidden) return;\n const color = this._color(index);\n this._tooltip.querySelectorAll<HTMLElement>('[data-series]').forEach((span) => {\n span.dataset.series = color;\n });\n }\n\n /** The tooltip sits where the ring's fill ends. */\n protected _place(index: number) {\n const turn = this._turn(this._fractions[index]);\n const r = this._radii[index];\n const [x, y] = [r * Math.sin(turn * 2 * Math.PI), -r * Math.cos(turn * 2 * Math.PI)];\n this._tooltip.style.left = `${50 + x}%`;\n this._tooltip.style.top = `${((50 + y) / (this._gauge ? 50 : 100)) * 100}%`;\n // On the right half it opens leftwards, over the rings.\n this._tooltip.classList.toggle('end', x > 0);\n }\n\n private _color(index: number) {\n return String((index % COLORS) + 1);\n }\n\n /** A fraction of the ring as a turn clockwise from the top. */\n private _turn(fraction: number) {\n return this._gauge ? fraction / 2 - 0.25 : fraction;\n }\n\n /** For more than one row, a legend of every row with its color and cell. */\n protected _guides(): Element[] {\n if (this.labels.length < 2) return [];\n const legend = document.createElement('ul');\n legend.className = 'radial-chart-legend';\n legend.setAttribute('aria-hidden', 'true');\n const text = this.series[0].text;\n legend.append(...this.labels.map((label, i) => {\n const li = document.createElement('li');\n li.dataset.series = this._color(i);\n const [name, value] = [label, text[i]].map((content) => {\n const span = document.createElement('span');\n span.textContent = content;\n return span;\n });\n li.append(name, value);\n return li;\n }));\n return [legend];\n }\n\n /** The ring under the pointer by its distance from the middle, or -1. */\n protected _indexAt(e: PointerEvent) {\n const box = this._plot.getBoundingClientRect();\n // The middle is half the width down in both shapes.\n const [x, y] = [e.clientX - box.left - box.width / 2, e.clientY - box.top - box.width / 2];\n if (this._gauge && y > 0) return -1;\n // The distance in the SVG's 100-unit box; a gap belongs to a ring beside it.\n const distance = (Math.hypot(x, y) / box.width) * 100;\n const step = this._radii.length > 1 ? this._radii[0] - this._radii[1] : this._width;\n return this._radii.findIndex((r) => Math.abs(distance - r) <= step / 2);\n }\n\n /**\n * An SVG of rings in a -50 to 50 box, the top half for a gauge. Each row\n * is a track circle and a fill circle whose dash is its share; CSS draws\n * them from --radial-chart-dash. The total is HTML over it.\n */\n protected _draw(): Element {\n const style = getComputedStyle(this.el);\n const token = (name: string, fallback: number) => {\n const value = parseFloat(style.getPropertyValue(`--md-comp-radial-chart-${name}`));\n return Number.isFinite(value) ? value : fallback;\n };\n const count = this.labels.length;\n let [width, gap] = [Math.max(0, token('thickness', 8)), Math.max(0, token('gap', 2))];\n // Too many rings to leave a middle thin, with their gaps, to fit.\n // ponytail: past about 18 rings they are hairlines; that many values want a bar chart.\n const scale = Math.min(1, (RADIUS * FILL) / (count * width + (count - 1) * gap || 1));\n [width, gap] = [width * scale, gap * scale];\n this._width = width;\n this._radii = this.labels.map((_, i) => RADIUS - width / 2 - i * (width + gap));\n // A maximum of zero or less means nothing, so it falls back.\n const max = [parseFloat(this.el.dataset.max ?? ''), this.options.max ?? NaN, 100].find((value) => value > 0)!;\n this._fractions = this.series[0].values.map((value) => Math.min(1, Math.max(0, (value ?? 0) / max)));\n\n const gauge = this._gauge;\n const svg = node('svg', { viewBox: gauge ? '-50 -50 100 50' : '-50 -50 100 100', focusable: 'false' });\n // A circle starts at three o'clock; turn it to the top, or to nine for a gauge.\n const transform = gauge ? 'rotate(180)' : 'rotate(-90)';\n const span = gauge ? 0.5 : 1;\n this._rings = this._radii.map((r, i) => {\n const length = 2 * Math.PI * r;\n // Round caps reach half the width past each end of a dash, so a capped\n // dash is one width shorter and starts half a width in. One shorter\n // than the width is a dot at the start.\n const circle = (name: string, fraction: number, capped: boolean) => {\n const ring = node('circle', { class: name, r: r.toFixed(3), transform, 'stroke-width': width.toFixed(3) });\n const dash = Math.max(0.001, fraction * span * length - (capped ? width : 0));\n ring.style.setProperty('--radial-chart-dash', `${dash.toFixed(3)} ${length.toFixed(3)}`);\n if (capped) ring.style.setProperty('--radial-chart-offset', (-width / 2).toFixed(3));\n return ring;\n };\n const ring = circle('radial-chart-ring', this._fractions[i], true) as SVGCircleElement;\n ring.dataset.series = this._color(i);\n // An empty ring would still draw its round cap.\n if (!this._fractions[i]) ring.classList.add('empty');\n // Only a gauge's track has ends to round.\n svg.append(circle('radial-chart-track', 1, gauge), ring);\n return ring;\n });\n\n const rings = document.createElement('div');\n rings.className = 'radial-chart-rings';\n rings.setAttribute('aria-hidden', 'true');\n rings.style.setProperty('--radial-chart-middle', `${(this._radii[count - 1] - this._width / 2) * 2}%`);\n rings.append(svg);\n\n const total = this._total('radial-chart-total');\n if (total) rings.append(total);\n return rings;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["ring"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import {
|
|
2
|
+
COLORS,
|
|
3
|
+
LineChart
|
|
4
|
+
} from "./chunk-O5XPWXIQ.mjs";
|
|
5
|
+
|
|
6
|
+
// src/ts/components/columnChart.ts
|
|
7
|
+
var ColumnChart = class extends LineChart {
|
|
8
|
+
get _type() {
|
|
9
|
+
return "column-chart";
|
|
10
|
+
}
|
|
11
|
+
get _key() {
|
|
12
|
+
return "Expressive_ColumnChart";
|
|
13
|
+
}
|
|
14
|
+
get _fromZero() {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
get _points() {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
static init(els, options = {}) {
|
|
21
|
+
return super.init(els, options);
|
|
22
|
+
}
|
|
23
|
+
static getInstance(el) {
|
|
24
|
+
return el["Expressive_ColumnChart"];
|
|
25
|
+
}
|
|
26
|
+
_draw(drawn = this.series) {
|
|
27
|
+
const columns = document.createElement("div");
|
|
28
|
+
columns.className = "column-chart-columns";
|
|
29
|
+
columns.setAttribute("aria-hidden", "true");
|
|
30
|
+
const clamp = (value, y = drawn[0]?.y ?? this._y) => Math.min(100, Math.max(0, y(value)));
|
|
31
|
+
columns.style.setProperty("--zero", `${clamp(0)}%`);
|
|
32
|
+
this._plot.style.setProperty("--rows", String(this.labels.length));
|
|
33
|
+
this.labels.forEach((_, index) => {
|
|
34
|
+
const row = document.createElement("div");
|
|
35
|
+
drawn.forEach((series) => {
|
|
36
|
+
const to = series.tops[index];
|
|
37
|
+
const from = series.base?.[index] ?? 0;
|
|
38
|
+
if (series.base && (to === null || from === null)) return;
|
|
39
|
+
const column = document.createElement("span");
|
|
40
|
+
if (to !== null) {
|
|
41
|
+
column.className = series.className;
|
|
42
|
+
column.dataset.series = String(this.series.indexOf(series) % COLORS + 1);
|
|
43
|
+
column.classList.toggle("negative", !series.base && to < from);
|
|
44
|
+
column.style.setProperty("--top", `${clamp(Math.max(from, to), series.y)}%`);
|
|
45
|
+
column.style.setProperty("--bottom", `${100 - clamp(Math.min(from, to), series.y)}%`);
|
|
46
|
+
if (this._horizontal) column.dataset.text = series.text[index];
|
|
47
|
+
}
|
|
48
|
+
row.append(column);
|
|
49
|
+
});
|
|
50
|
+
columns.append(row);
|
|
51
|
+
});
|
|
52
|
+
return columns;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export {
|
|
57
|
+
ColumnChart
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=chunk-SPETGK25.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/ts/components/columnChart.ts"],
|
|
4
|
+
"sourcesContent": ["import { InitElements, InitElement } from '../core/component';\nimport { COLORS, LineChart, LineChartOptions } from './lineChart';\n\nexport type ColumnChartOptions = LineChartOptions;\n\n/**\n * Column chart. It reads its <table>, scales, labels and tooltip like\n * LineChart, but draws each row as a group of columns from zero, or one\n * column of segments with `stacked`. Columns are HTML clipped to their\n * value, so their rounded corners keep their shape at any size.\n *\n * Re-run `ColumnChart.init(el)` after changing the table.\n */\nexport class ColumnChart extends LineChart {\n protected get _type() {\n return 'column-chart';\n }\n\n protected get _key() {\n return 'Expressive_ColumnChart';\n }\n\n protected get _fromZero() {\n return true;\n }\n\n protected get _points() {\n return false;\n }\n\n static init(el: HTMLElement, options?: Partial<ColumnChartOptions>): ColumnChart;\n static init(els: InitElements<InitElement>, options?: Partial<ColumnChartOptions>): ColumnChart[];\n static init(\n els: HTMLElement | InitElements<InitElement>,\n options: Partial<ColumnChartOptions> = {}\n ): ColumnChart | ColumnChart[] {\n return super.init(els as HTMLElement, options) as ColumnChart | ColumnChart[];\n }\n\n static getInstance(el: HTMLElement): ColumnChart {\n return el['Expressive_ColumnChart'];\n }\n\n protected _draw(drawn = this.series): Element {\n const columns = document.createElement('div');\n columns.className = 'column-chart-columns';\n columns.setAttribute('aria-hidden', 'true');\n const clamp = (value: number, y = drawn[0]?.y ?? this._y) => Math.min(100, Math.max(0, y(value)));\n // Columns grow from zero, or from the plot edge when zero is off the scale.\n columns.style.setProperty('--zero', `${clamp(0)}%`);\n this._plot.style.setProperty('--rows', String(this.labels.length));\n\n this.labels.forEach((_, index) => {\n const row = document.createElement('div');\n drawn.forEach((series) => {\n // A stacked segment above a gap has no known base, so it is left out.\n const to = series.tops[index];\n const from = series.base?.[index] ?? 0;\n if (series.base && (to === null || from === null)) return;\n const column = document.createElement('span');\n // A gap in a grouped row keeps its empty slot, so the series stay aligned.\n if (to !== null) {\n column.className = series.className;\n column.dataset.series = String((this.series.indexOf(series) % COLORS) + 1);\n // A stacked segment never hangs from zero, so it keeps the top rounding.\n column.classList.toggle('negative', !series.base && to < from);\n column.style.setProperty('--top', `${clamp(Math.max(from, to), series.y)}%`);\n column.style.setProperty('--bottom', `${100 - clamp(Math.min(from, to), series.y)}%`);\n // The cell text, which a bar chart with .values writes along its bar.\n if (this._horizontal) column.dataset.text = series.text[index];\n }\n row.append(column);\n });\n columns.append(row);\n });\n return columns;\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;AAaO,IAAM,cAAN,cAA0B,UAAU;AAAA,EACzC,IAAc,QAAQ;AACpB,WAAO;AAAA,EACT;AAAA,EAEA,IAAc,OAAO;AACnB,WAAO;AAAA,EACT;AAAA,EAEA,IAAc,YAAY;AACxB,WAAO;AAAA,EACT;AAAA,EAEA,IAAc,UAAU;AACtB,WAAO;AAAA,EACT;AAAA,EAIA,OAAO,KACL,KACA,UAAuC,CAAC,GACX;AAC7B,WAAO,MAAM,KAAK,KAAoB,OAAO;AAAA,EAC/C;AAAA,EAEA,OAAO,YAAY,IAA8B;AAC/C,WAAO,GAAG,wBAAwB;AAAA,EACpC;AAAA,EAEU,MAAM,QAAQ,KAAK,QAAiB;AAC5C,UAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,YAAQ,YAAY;AACpB,YAAQ,aAAa,eAAe,MAAM;AAC1C,UAAM,QAAQ,CAAC,OAAe,IAAI,MAAM,CAAC,GAAG,KAAK,KAAK,OAAO,KAAK,IAAI,KAAK,KAAK,IAAI,GAAG,EAAE,KAAK,CAAC,CAAC;AAEhG,YAAQ,MAAM,YAAY,UAAU,GAAG,MAAM,CAAC,CAAC,GAAG;AAClD,SAAK,MAAM,MAAM,YAAY,UAAU,OAAO,KAAK,OAAO,MAAM,CAAC;AAEjE,SAAK,OAAO,QAAQ,CAAC,GAAG,UAAU;AAChC,YAAM,MAAM,SAAS,cAAc,KAAK;AACxC,YAAM,QAAQ,CAAC,WAAW;AAExB,cAAM,KAAK,OAAO,KAAK,KAAK;AAC5B,cAAM,OAAO,OAAO,OAAO,KAAK,KAAK;AACrC,YAAI,OAAO,SAAS,OAAO,QAAQ,SAAS,MAAO;AACnD,cAAM,SAAS,SAAS,cAAc,MAAM;AAE5C,YAAI,OAAO,MAAM;AACf,iBAAO,YAAY,OAAO;AAC1B,iBAAO,QAAQ,SAAS,OAAQ,KAAK,OAAO,QAAQ,MAAM,IAAI,SAAU,CAAC;AAEzE,iBAAO,UAAU,OAAO,YAAY,CAAC,OAAO,QAAQ,KAAK,IAAI;AAC7D,iBAAO,MAAM,YAAY,SAAS,GAAG,MAAM,KAAK,IAAI,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG;AAC3E,iBAAO,MAAM,YAAY,YAAY,GAAG,MAAM,MAAM,KAAK,IAAI,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,GAAG;AAEpF,cAAI,KAAK,YAAa,QAAO,QAAQ,OAAO,OAAO,KAAK,KAAK;AAAA,QAC/D;AACA,YAAI,OAAO,MAAM;AAAA,MACnB,CAAC;AACD,cAAQ,OAAO,GAAG;AAAA,IACpB,CAAC;AACD,WAAO;AAAA,EACT;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Utils
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6OMRGML6.mjs";
|
|
4
4
|
import {
|
|
5
5
|
Component
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LTWPGFBR.mjs";
|
|
7
7
|
|
|
8
8
|
// src/ts/components/menu.ts
|
|
9
9
|
var MIN_SURFACE_WIDTH = 112;
|
|
@@ -16,6 +16,7 @@ var _defaults = {
|
|
|
16
16
|
coverTrigger: false,
|
|
17
17
|
closeOnClick: true,
|
|
18
18
|
hover: false,
|
|
19
|
+
contextMenu: false,
|
|
19
20
|
inDuration: 150,
|
|
20
21
|
outDuration: 250,
|
|
21
22
|
onOpenStart: null,
|
|
@@ -30,6 +31,41 @@ var _Menu = class _Menu extends Component {
|
|
|
30
31
|
super(el, options, _Menu);
|
|
31
32
|
this._pendingTimers = /* @__PURE__ */ new Set();
|
|
32
33
|
this._transition = 0;
|
|
34
|
+
this._menuClickTargets = /* @__PURE__ */ new WeakMap();
|
|
35
|
+
/**
|
|
36
|
+
* Viewport point the open context menu belongs to. Null outside a
|
|
37
|
+
* right-click, so a keyboard or programmatic open uses the region's corner
|
|
38
|
+
* rather than an old pointer position.
|
|
39
|
+
*/
|
|
40
|
+
this._contextPoint = null;
|
|
41
|
+
/** What had focus when a context menu opened; focus goes back there. */
|
|
42
|
+
this._contextReturn = null;
|
|
43
|
+
this._handleContextMenu = (e) => {
|
|
44
|
+
if (e.defaultPrevented) {
|
|
45
|
+
this.close();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const path = e.composedPath();
|
|
49
|
+
if (_Menu._menus.some((menu) => menu !== this && menu.isOpen && path.includes(menu.menuEl))) return;
|
|
50
|
+
e.preventDefault();
|
|
51
|
+
if (!this.isOpen) {
|
|
52
|
+
const root = this.el.getRootNode();
|
|
53
|
+
this._contextReturn = root.activeElement instanceof HTMLElement ? root.activeElement : null;
|
|
54
|
+
}
|
|
55
|
+
const rect = this.el.getBoundingClientRect();
|
|
56
|
+
const fromPointer = (e.clientX !== 0 || e.clientY !== 0) && e.clientX >= rect.left && e.clientX <= rect.right && e.clientY >= rect.top && e.clientY <= rect.bottom;
|
|
57
|
+
this._contextPoint = fromPointer ? { x: e.clientX, y: e.clientY } : null;
|
|
58
|
+
if (this.isOpen) this.recalculateDimensions();
|
|
59
|
+
else this.open();
|
|
60
|
+
};
|
|
61
|
+
this._handleDocumentContextMenu = (e) => {
|
|
62
|
+
const path = e.composedPath();
|
|
63
|
+
if (path.includes(this.menuEl)) {
|
|
64
|
+
e.preventDefault();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!path.includes(this.el)) this.close();
|
|
68
|
+
};
|
|
33
69
|
this._handleClick = (e) => {
|
|
34
70
|
e.preventDefault();
|
|
35
71
|
if (this.isOpen) {
|
|
@@ -58,11 +94,15 @@ var _Menu = class _Menu extends Component {
|
|
|
58
94
|
}
|
|
59
95
|
};
|
|
60
96
|
this._handleDocumentClick = (e) => {
|
|
61
|
-
const
|
|
97
|
+
const path = e.composedPath();
|
|
98
|
+
const menuTarget = this._menuClickTargets.get(e);
|
|
99
|
+
this._menuClickTargets.delete(e);
|
|
100
|
+
const target = menuTarget ?? (path[0] || e.target);
|
|
101
|
+
const inside = !!menuTarget || path.includes(this.menuEl) || this.menuEl?.contains(target);
|
|
62
102
|
if (this._isSubmenuTriggerClick(target)) return;
|
|
63
|
-
if (this.options.closeOnClick &&
|
|
103
|
+
if (this.options.closeOnClick && inside && !this.isTouchMoving) {
|
|
64
104
|
this.close();
|
|
65
|
-
} else if (!
|
|
105
|
+
} else if (!inside) {
|
|
66
106
|
this._schedule(() => {
|
|
67
107
|
if (this.isOpen) {
|
|
68
108
|
this.close();
|
|
@@ -72,6 +112,7 @@ var _Menu = class _Menu extends Component {
|
|
|
72
112
|
this.isTouchMoving = false;
|
|
73
113
|
};
|
|
74
114
|
this._handleTriggerKeydown = (e) => {
|
|
115
|
+
if (this.options.contextMenu) return;
|
|
75
116
|
const opensMenu = e.key === SPACE || e.key === Utils.keys.ENTER || e.key === Utils.keys.ARROW_DOWN || e.key === Utils.keys.ARROW_UP;
|
|
76
117
|
if (opensMenu && !this.isOpen) {
|
|
77
118
|
e.preventDefault();
|
|
@@ -80,12 +121,13 @@ var _Menu = class _Menu extends Component {
|
|
|
80
121
|
};
|
|
81
122
|
this._handleDocumentTouchmove = (e) => {
|
|
82
123
|
const target = e.target;
|
|
83
|
-
if (this.menuEl?.contains(target)) {
|
|
124
|
+
if (e.composedPath().includes(this.menuEl) || this.menuEl?.contains(target)) {
|
|
84
125
|
this.isTouchMoving = true;
|
|
85
126
|
}
|
|
86
127
|
};
|
|
87
128
|
this._handleMenuClick = (e) => {
|
|
88
129
|
const target = e.target;
|
|
130
|
+
this._menuClickTargets.set(e, target);
|
|
89
131
|
const li = target.closest("li");
|
|
90
132
|
if (li?.matches('.disabled, [aria-disabled="true"]')) {
|
|
91
133
|
e.preventDefault();
|
|
@@ -229,7 +271,7 @@ var _Menu = class _Menu extends Component {
|
|
|
229
271
|
this._placeMenu();
|
|
230
272
|
this._schedule(() => this._setupTemporaryEventHandlers(), 0);
|
|
231
273
|
this._animateIn();
|
|
232
|
-
this.
|
|
274
|
+
this._setExpanded(true);
|
|
233
275
|
};
|
|
234
276
|
/**
|
|
235
277
|
* Close menu.
|
|
@@ -251,10 +293,13 @@ var _Menu = class _Menu extends Component {
|
|
|
251
293
|
if (transition !== this._transition) return;
|
|
252
294
|
this._animateOut();
|
|
253
295
|
this._removeTemporaryEventHandlers();
|
|
254
|
-
this.
|
|
255
|
-
if (this.options.autoFocus && (root.activeElement === focused ||
|
|
256
|
-
this.
|
|
296
|
+
this._setExpanded(false);
|
|
297
|
+
if (this.options.autoFocus && this.menuEl.contains(focused) && (root.activeElement === focused || this.el.ownerDocument.activeElement === this.el.ownerDocument.body)) {
|
|
298
|
+
const back = this._contextReturn;
|
|
299
|
+
(back?.isConnected && back !== this.el.ownerDocument.body ? back : this.el).focus();
|
|
257
300
|
}
|
|
301
|
+
this._contextReturn = null;
|
|
302
|
+
this._contextPoint = null;
|
|
258
303
|
};
|
|
259
304
|
/**
|
|
260
305
|
* While menu is open, you can recalculate its dimensions if its contents have changed.
|
|
@@ -272,6 +317,7 @@ var _Menu = class _Menu extends Component {
|
|
|
272
317
|
this._originalInert = this.menuEl?.getAttribute("inert") ?? null;
|
|
273
318
|
this.options = {
|
|
274
319
|
..._Menu.defaults,
|
|
320
|
+
contextMenu: el.hasAttribute("data-context-menu"),
|
|
275
321
|
...options
|
|
276
322
|
};
|
|
277
323
|
this.isOpen = false;
|
|
@@ -279,10 +325,12 @@ var _Menu = class _Menu extends Component {
|
|
|
279
325
|
this.isTouchMoving = false;
|
|
280
326
|
this.focusedIndex = -1;
|
|
281
327
|
this.filterQuery = [];
|
|
282
|
-
this.
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
this.el.
|
|
328
|
+
if (!this.options.contextMenu) {
|
|
329
|
+
this.el.ariaExpanded = "false";
|
|
330
|
+
if (!this.el.hasAttribute("aria-haspopup")) this.el.setAttribute("aria-haspopup", "menu");
|
|
331
|
+
if (this.id && !this.el.hasAttribute("aria-controls"))
|
|
332
|
+
this.el.setAttribute("aria-controls", this.id);
|
|
333
|
+
}
|
|
286
334
|
this._moveMenuToElement();
|
|
287
335
|
this._setupAccessibility();
|
|
288
336
|
this._makeMenuFocusable();
|
|
@@ -306,7 +354,7 @@ var _Menu = class _Menu extends Component {
|
|
|
306
354
|
destroy() {
|
|
307
355
|
this._clearPendingTimers();
|
|
308
356
|
this.isOpen = false;
|
|
309
|
-
this.
|
|
357
|
+
this._setExpanded(false);
|
|
310
358
|
clearTimeout(this.filterTimeout);
|
|
311
359
|
this._resetMenuStyles();
|
|
312
360
|
this._restoreInert();
|
|
@@ -322,7 +370,9 @@ var _Menu = class _Menu extends Component {
|
|
|
322
370
|
if (this.menuEl?.querySelector(":scope > li > menu")) {
|
|
323
371
|
this.menuEl.addEventListener("mouseover", this._handleSubmenuAlign);
|
|
324
372
|
}
|
|
325
|
-
if (this.options.
|
|
373
|
+
if (this.options.contextMenu) {
|
|
374
|
+
this.el.addEventListener("contextmenu", this._handleContextMenu);
|
|
375
|
+
} else if (this.options.hover) {
|
|
326
376
|
this.el.addEventListener("mouseenter", this._handleMouseEnter);
|
|
327
377
|
this.el.addEventListener("mouseleave", this._handleMouseLeave);
|
|
328
378
|
this.menuEl.addEventListener("mouseleave", this._handleMouseLeave);
|
|
@@ -334,7 +384,9 @@ var _Menu = class _Menu extends Component {
|
|
|
334
384
|
this.el.removeEventListener("keydown", this._handleTriggerKeydown);
|
|
335
385
|
this.menuEl?.removeEventListener("click", this._handleMenuClick);
|
|
336
386
|
this.menuEl?.removeEventListener("mouseover", this._handleSubmenuAlign);
|
|
337
|
-
if (this.options.
|
|
387
|
+
if (this.options.contextMenu) {
|
|
388
|
+
this.el.removeEventListener("contextmenu", this._handleContextMenu);
|
|
389
|
+
} else if (this.options.hover) {
|
|
338
390
|
this.el.removeEventListener("mouseenter", this._handleMouseEnter);
|
|
339
391
|
this.el.removeEventListener("mouseleave", this._handleMouseLeave);
|
|
340
392
|
this.menuEl?.removeEventListener("mouseleave", this._handleMouseLeave);
|
|
@@ -344,17 +396,21 @@ var _Menu = class _Menu extends Component {
|
|
|
344
396
|
}
|
|
345
397
|
_setupTemporaryEventHandlers() {
|
|
346
398
|
document.body.addEventListener("click", this._handleDocumentClick);
|
|
399
|
+
this.menuEl?.addEventListener("touchmove", this._handleDocumentTouchmove, { passive: true });
|
|
347
400
|
document.body.addEventListener("touchmove", this._handleDocumentTouchmove, {
|
|
348
401
|
passive: true
|
|
349
402
|
});
|
|
350
403
|
this.menuEl?.addEventListener("keydown", this._handleMenuKeydown);
|
|
351
404
|
window.addEventListener("resize", this._handleWindowResize);
|
|
405
|
+
if (this.options.contextMenu) document.addEventListener("contextmenu", this._handleDocumentContextMenu);
|
|
352
406
|
}
|
|
353
407
|
_removeTemporaryEventHandlers() {
|
|
354
408
|
document.body.removeEventListener("click", this._handleDocumentClick);
|
|
409
|
+
this.menuEl?.removeEventListener("touchmove", this._handleDocumentTouchmove);
|
|
355
410
|
document.body.removeEventListener("touchmove", this._handleDocumentTouchmove);
|
|
356
411
|
this.menuEl?.removeEventListener("keydown", this._handleMenuKeydown);
|
|
357
412
|
window.removeEventListener("resize", this._handleWindowResize);
|
|
413
|
+
document.removeEventListener("contextmenu", this._handleDocumentContextMenu);
|
|
358
414
|
}
|
|
359
415
|
_setupAccessibility() {
|
|
360
416
|
if (!this.menuEl) return;
|
|
@@ -644,8 +700,12 @@ var _Menu = class _Menu extends Component {
|
|
|
644
700
|
closestOverflowParent.style.position = "relative";
|
|
645
701
|
const natural = this.menuEl.getBoundingClientRect().width;
|
|
646
702
|
const triggerWidth = this.el.getBoundingClientRect().width;
|
|
647
|
-
const idealWidth = this.options.constrainWidth && triggerWidth >= MIN_SURFACE_WIDTH ? triggerWidth : Math.min(MAX_SURFACE_WIDTH, Math.max(MIN_SURFACE_WIDTH, natural));
|
|
703
|
+
const idealWidth = this.options.constrainWidth && !this.options.contextMenu && triggerWidth >= MIN_SURFACE_WIDTH ? triggerWidth : Math.min(MAX_SURFACE_WIDTH, Math.max(MIN_SURFACE_WIDTH, natural));
|
|
648
704
|
this.menuEl.style.width = idealWidth + "px";
|
|
705
|
+
if (this.options.contextMenu) {
|
|
706
|
+
this._placeMenuAtPoint(this._contextPoint ?? this._regionCorner(), closestOverflowParent);
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
649
709
|
const positionInfo = this._getMenuPosition(closestOverflowParent);
|
|
650
710
|
this.menuEl.style.left = positionInfo.x + "px";
|
|
651
711
|
this.menuEl.style.top = positionInfo.y + "px";
|
|
@@ -653,6 +713,58 @@ var _Menu = class _Menu extends Component {
|
|
|
653
713
|
this.menuEl.style.width = positionInfo.width + "px";
|
|
654
714
|
this.menuEl.style.transformOrigin = `${positionInfo.horizontalAlignment === "left" ? "0" : "100%"} ${positionInfo.verticalAlignment === "top" ? "0" : "100%"}`;
|
|
655
715
|
}
|
|
716
|
+
/** Where a context menu opens without a pointer: the region's start corner. */
|
|
717
|
+
_regionCorner() {
|
|
718
|
+
const rect = this.el.getBoundingClientRect();
|
|
719
|
+
const rtl = getComputedStyle(this.el).direction === "rtl";
|
|
720
|
+
return { x: rtl ? rect.right : rect.left, y: rect.bottom };
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Places a context menu with its start corner on the point, flipping to
|
|
724
|
+
* the other side of the point where it would not fit. The bounds are the
|
|
725
|
+
* viewport, narrowed to a scrolling or clipping ancestor the menu sits in;
|
|
726
|
+
* a menu taller than them gets their height and scrolls.
|
|
727
|
+
*
|
|
728
|
+
* The menu rests at left/top 0 of its containing block, so its rect is the
|
|
729
|
+
* offset to subtract - the same trick _getMenuPosition uses. It is measured
|
|
730
|
+
* without the entry animation's scale, which a second right-click can catch.
|
|
731
|
+
*/
|
|
732
|
+
_placeMenuAtPoint({ x, y }, container) {
|
|
733
|
+
const { transform, transition } = this.menuEl.style;
|
|
734
|
+
this.menuEl.style.transition = "none";
|
|
735
|
+
this.menuEl.style.transform = "none";
|
|
736
|
+
const menu = this.menuEl.getBoundingClientRect();
|
|
737
|
+
this.menuEl.style.transform = transform;
|
|
738
|
+
this.menuEl.style.transition = transition;
|
|
739
|
+
let bounds = { left: 0, top: 0, right: window.innerWidth, bottom: window.innerHeight };
|
|
740
|
+
if (container && getComputedStyle(container).overflow !== "visible") {
|
|
741
|
+
const clip = container.getBoundingClientRect();
|
|
742
|
+
bounds = {
|
|
743
|
+
left: Math.max(bounds.left, clip.left),
|
|
744
|
+
top: Math.max(bounds.top, clip.top),
|
|
745
|
+
right: Math.min(bounds.right, clip.right),
|
|
746
|
+
bottom: Math.min(bounds.bottom, clip.bottom)
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
const width = menu.width;
|
|
750
|
+
const height = Math.min(menu.height, bounds.bottom - bounds.top);
|
|
751
|
+
this.isScrollable = height < menu.height;
|
|
752
|
+
if (this.isScrollable) this.menuEl.style.height = height + "px";
|
|
753
|
+
const rtl = getComputedStyle(this.el).direction === "rtl";
|
|
754
|
+
const fitsRight = x + width <= bounds.right;
|
|
755
|
+
const fitsLeft = x - width >= bounds.left;
|
|
756
|
+
const leftward = rtl ? fitsLeft || !fitsRight : !fitsRight && fitsLeft;
|
|
757
|
+
const upward = y + height > bounds.bottom && y - height >= bounds.top;
|
|
758
|
+
const clamp = (value, min, max) => Math.max(min, Math.min(value, max));
|
|
759
|
+
const left = clamp(leftward ? x - width : x, bounds.left, bounds.right - width);
|
|
760
|
+
const top = clamp(upward ? y - height : y, bounds.top, bounds.bottom - height);
|
|
761
|
+
this.menuEl.style.left = left - menu.left + "px";
|
|
762
|
+
this.menuEl.style.top = top - menu.top + "px";
|
|
763
|
+
this.menuEl.style.transformOrigin = `${leftward ? "100%" : "0"} ${upward ? "100%" : "0"}`;
|
|
764
|
+
}
|
|
765
|
+
_setExpanded(expanded) {
|
|
766
|
+
if (!this.options.contextMenu) this.el.ariaExpanded = String(expanded);
|
|
767
|
+
}
|
|
656
768
|
};
|
|
657
769
|
_Menu._menus = [];
|
|
658
770
|
var Menu = _Menu;
|
|
@@ -660,4 +772,4 @@ var Menu = _Menu;
|
|
|
660
772
|
export {
|
|
661
773
|
Menu
|
|
662
774
|
};
|
|
663
|
-
//# sourceMappingURL=chunk-
|
|
775
|
+
//# sourceMappingURL=chunk-U2OTHOTI.mjs.map
|