umberto 7.0.2 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -1799
- package/LICENSE.md +44 -5
- package/README.md +194 -9
- package/package.json +4 -8
- package/scripts/filter/after-post-render/gloria/append-copy-heading-buttons.js +99 -0
- package/scripts/filter/after-post-render/gloria/apply-design-doc-classes.js +145 -0
- package/scripts/filter/after-post-render/gloria/wrap-table-into-wrappers.js +30 -0
- package/scripts/filter/after-post-render/img-linker.js +1 -1
- package/scripts/filter/after-post-render/insert-error-codes.js +1 -1
- package/scripts/filter/after-post-render/linker.js +1 -1
- package/scripts/filter/after-post-render/snippets.js +5 -1
- package/scripts/filter/after-render/gloria/inline-svg.js +14 -0
- package/scripts/filter/after-render/gloria/spritesheet-svg.js +14 -0
- package/scripts/filter/before-post-render/add-project-info-to-page.js +1 -1
- package/scripts/filter/before-post-render/code-switcher.js +4 -0
- package/scripts/filter/before-post-render/execute-and-insert-function-results.js +3 -1
- package/scripts/filter/before-post-render/gloria/add-breadcrumbs-data-to-page.js +269 -0
- package/scripts/filter/before-post-render/gloria/prerender-admonitions.js +27 -0
- package/scripts/filter/before-post-render/gloria/prerender-xml-pug-components.js +339 -0
- package/scripts/filter/before-post-render/gloria/render-post-render-pug-components.js +94 -0
- package/scripts/filter/before-post-render/set-layout.js +4 -2
- package/scripts/helper/parse-href.js +28 -0
- package/scripts/helper/u-capitalize.js +13 -0
- package/scripts/helper/u-random-id.js +16 -0
- package/scripts/helper/u-remove-indentation.js +13 -0
- package/scripts/helper/u-toc.js +2 -63
- package/scripts/utils/add-indention.js +16 -0
- package/scripts/utils/capitalize.js +17 -0
- package/scripts/utils/concat-url-parts.js +19 -0
- package/scripts/utils/decode-html-entities.js +25 -0
- package/scripts/utils/drop-init-slash.js +14 -0
- package/scripts/utils/drop-trailing-slash.js +14 -0
- package/scripts/utils/drop-url-protocol.js +10 -0
- package/scripts/utils/inline-svg.js +152 -0
- package/scripts/utils/measure-call.js +16 -0
- package/scripts/utils/parse-href.js +37 -0
- package/scripts/utils/parseicontag.js +1 -1
- package/scripts/utils/parselinks.js +27 -6
- package/scripts/utils/parser-cursor.js +280 -0
- package/scripts/utils/pipe.js +17 -0
- package/scripts/utils/pug-renderer/create-prerender-pug-template.js +172 -0
- package/scripts/utils/pug-renderer/render-pug-component.js +73 -0
- package/scripts/utils/pug-to-xml-binding/parser/walk-xml-tree.js +150 -0
- package/scripts/utils/pug-to-xml-binding/parser/xml-components-parser.js +414 -0
- package/scripts/utils/pug-to-xml-binding/render-xml-pug-components-in-markdown.js +193 -0
- package/scripts/utils/pug-to-xml-binding/transform-xml-tree-to-pug.js +144 -0
- package/scripts/utils/random-id.js +67 -0
- package/scripts/utils/remove-indentation.js +48 -0
- package/scripts/utils/spritesheet-svg.js +183 -0
- package/scripts/utils/toc.js +71 -0
- package/scripts/utils/transform-markdown-admonitions.js +98 -0
- package/scripts/utils/uniq-by-last.js +32 -0
- package/src/api-builder/api-builder.js +49 -18
- package/src/api-builder/classes/description-parser.js +61 -10
- package/src/api-builder/classes/doc-data-factory.js +2 -2
- package/src/helpers/github-url.js +1 -1
- package/src/helpers/templates/scripts/default.js +1 -1
- package/src/helpers/templates/scripts/group.js +1 -1
- package/src/hexo/filter/project-locals.js +9 -0
- package/src/hexo/get-repo-urls.js +1 -1
- package/src/hexo/project-globals.js +4 -0
- package/src/hexo-manager.js +7 -2
- package/src/sdk-builder/sdk-builder.js +4 -4
- package/src/tasks/build-api-docs.js +5 -5
- package/src/tasks/build-documentation.js +45 -22
- package/src/tasks/cache-files.js +2 -2
- package/src/tasks/compile-sass.js +12 -0
- package/src/tasks/copy-assets.js +4 -0
- package/src/tasks/copy-project-icons.js +1 -1
- package/src/tasks/get-extra-files.js +1 -1
- package/src/tasks/get-project-config.js +1 -1
- package/src/tasks/overwrite-api-guides.js +1 -1
- package/themes/umberto/layout/gloria/404.pug +25 -16
- package/themes/umberto/layout/gloria/_api-docs/_header/_style.scss +31 -0
- package/themes/umberto/layout/gloria/_api-docs/_header/index.pug +50 -0
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_api-see-source.pug +1 -4
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_api-tree-item.pug +34 -26
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_class-item.pug +20 -13
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_dev-names.pug +1 -1
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_error.pug +10 -5
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_hierarchy-list.pug +1 -1
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_link-or-text.pug +1 -1
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_method.pug +45 -39
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_property.pug +26 -20
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_related.pug +1 -1
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_toc-list-item.pug +11 -0
- package/themes/umberto/layout/gloria/_api-docs/_partial/api-subheader.pug +0 -11
- package/themes/umberto/layout/gloria/_api-docs/_partial/api-toc.pug +33 -0
- package/themes/umberto/layout/gloria/_api-docs/_partial/classes.pug +5 -4
- package/themes/umberto/layout/gloria/_api-docs/_partial/config-options.pug +5 -4
- package/themes/umberto/layout/gloria/_api-docs/_partial/constants.pug +1 -1
- package/themes/umberto/layout/gloria/_api-docs/_partial/description.pug +2 -2
- package/themes/umberto/layout/gloria/_api-docs/_partial/events.pug +5 -4
- package/themes/umberto/layout/gloria/_api-docs/_partial/functions.pug +5 -4
- package/themes/umberto/layout/gloria/_api-docs/_partial/interfaces.pug +1 -1
- package/themes/umberto/layout/gloria/_api-docs/_partial/methods.pug +14 -13
- package/themes/umberto/layout/gloria/_api-docs/_partial/namespaces.pug +1 -1
- package/themes/umberto/layout/gloria/_api-docs/_partial/navtree.pug +4 -11
- package/themes/umberto/layout/gloria/_api-docs/_partial/properties.pug +14 -13
- package/themes/umberto/layout/gloria/_api-docs/_partial/type-parameters.pug +15 -12
- package/themes/umberto/layout/gloria/_api-docs/_partial/typedefs.pug +5 -4
- package/themes/umberto/layout/gloria/_api-docs/_subheader/_style.scss +5 -0
- package/themes/umberto/layout/gloria/_api-docs/_subheader/index.pug +10 -0
- package/themes/umberto/layout/gloria/_api-docs/_toc/_style.scss +227 -0
- package/themes/umberto/layout/gloria/_api-docs/_toc/index.pug +11 -0
- package/themes/umberto/layout/gloria/_api-docs/api-base.pug +24 -24
- package/themes/umberto/layout/gloria/_api-docs/class.pug +4 -4
- package/themes/umberto/layout/gloria/_api-docs/errors.pug +3 -3
- package/themes/umberto/layout/gloria/_api-docs/index.pug +3 -0
- package/themes/umberto/layout/gloria/_api-docs/interface.pug +4 -4
- package/themes/umberto/layout/gloria/_api-docs/mixin.pug +4 -4
- package/themes/umberto/layout/gloria/_api-docs/module.pug +4 -4
- package/themes/umberto/layout/gloria/_api-docs/namespace.pug +4 -4
- package/themes/umberto/layout/gloria/_api-docs/typedef.pug +22 -22
- package/themes/umberto/layout/gloria/_components/badge/_style.scss +27 -0
- package/themes/umberto/layout/gloria/_components/badge/index.pug +30 -0
- package/themes/umberto/layout/gloria/_components/banner/_style.scss +133 -0
- package/themes/umberto/layout/gloria/_components/banner/index.pug +3 -0
- package/themes/umberto/layout/gloria/_components/button/_style.scss +183 -0
- package/themes/umberto/layout/gloria/_components/button/index.pug +140 -0
- package/themes/umberto/layout/gloria/_components/callout/_style.scss +56 -0
- package/themes/umberto/layout/gloria/_components/callout/index.pug +87 -0
- package/themes/umberto/layout/gloria/_components/card/_style.scss +101 -0
- package/themes/umberto/layout/gloria/_components/card/index.pug +131 -0
- package/themes/umberto/layout/gloria/_components/card-learn-more-links/_style.scss +9 -0
- package/themes/umberto/layout/gloria/_components/card-learn-more-links/index.pug +56 -0
- package/themes/umberto/layout/gloria/_components/checkbox/_style.scss +117 -0
- package/themes/umberto/layout/gloria/_components/checkbox/index.pug +35 -0
- package/themes/umberto/layout/gloria/_components/cke5-code-switcher/index.pug +39 -0
- package/themes/umberto/layout/gloria/_components/code-block/_style.scss +111 -0
- package/themes/umberto/layout/gloria/_components/code-block/index.pug +67 -0
- package/themes/umberto/layout/gloria/_components/code-switcher/_style.scss +41 -0
- package/themes/umberto/layout/gloria/_components/code-switcher/index.pug +31 -0
- package/themes/umberto/layout/gloria/_components/columns/_style.scss +54 -0
- package/themes/umberto/layout/gloria/_components/columns/index.pug +30 -0
- package/themes/umberto/layout/gloria/_components/divider/_style.scss +6 -0
- package/themes/umberto/layout/gloria/_components/divider/index.pug +13 -0
- package/themes/umberto/layout/gloria/_components/dropdown/_style.scss +88 -0
- package/themes/umberto/layout/gloria/_components/dropdown/index.pug +77 -0
- package/themes/umberto/layout/gloria/_components/fake-devtools/_style.scss +233 -0
- package/themes/umberto/layout/gloria/_components/fake-devtools/index.pug +27 -0
- package/themes/umberto/layout/gloria/_components/heading-badge/index.pug +17 -0
- package/themes/umberto/layout/gloria/_components/heading-link/_style.scss +47 -0
- package/themes/umberto/layout/gloria/_components/heading-link/index.pug +26 -0
- package/themes/umberto/layout/gloria/_components/icon/_style.scss +12 -0
- package/themes/umberto/layout/gloria/_components/icon/index.pug +75 -0
- package/themes/umberto/layout/gloria/_components/icon-message/_style.scss +13 -0
- package/themes/umberto/layout/gloria/_components/icon-message/index.pug +17 -0
- package/themes/umberto/layout/gloria/_components/iframe/_style.scss +10 -0
- package/themes/umberto/layout/gloria/_components/iframe/index.pug +22 -0
- package/themes/umberto/layout/gloria/_components/img/index.pug +17 -0
- package/themes/umberto/layout/gloria/_components/index.pug +31 -0
- package/themes/umberto/layout/gloria/_components/input/_style.scss +82 -0
- package/themes/umberto/layout/gloria/_components/input/index.pug +34 -0
- package/themes/umberto/layout/gloria/_components/json-ld/index.pug +3 -0
- package/themes/umberto/layout/gloria/_components/keyboard-shortcut/_style.scss +49 -0
- package/themes/umberto/layout/gloria/_components/keyboard-shortcut/index.pug +23 -0
- package/themes/umberto/layout/gloria/_components/menu-dropdown/_style.scss +27 -0
- package/themes/umberto/layout/gloria/_components/menu-dropdown/index.pug +40 -0
- package/themes/umberto/layout/gloria/_components/mobile-overlay/_style.scss +70 -0
- package/themes/umberto/layout/gloria/_components/mobile-overlay/index.pug +37 -0
- package/themes/umberto/layout/gloria/_components/nav-tree/_style.scss +104 -0
- package/themes/umberto/layout/gloria/_components/nav-tree/index.pug +6 -0
- package/themes/umberto/layout/gloria/_components/nav-tree/nav-tree-item.pug +23 -0
- package/themes/umberto/layout/gloria/{_mixin → _components/nav-tree}/nav-tree-level.pug +31 -11
- package/themes/umberto/layout/gloria/_components/skeleton/_style.scss +22 -0
- package/themes/umberto/layout/gloria/_components/skeleton/index.pug +16 -0
- package/themes/umberto/layout/gloria/_components/spacer/_style.scss +9 -0
- package/themes/umberto/layout/gloria/_components/spacer/index.pug +19 -0
- package/themes/umberto/layout/gloria/_components/svg/index.pug +70 -0
- package/themes/umberto/layout/gloria/_components/tabs/_style.scss +80 -0
- package/themes/umberto/layout/gloria/_components/tabs/index.pug +81 -0
- package/themes/umberto/layout/gloria/_components/tag/_style.scss +79 -0
- package/themes/umberto/layout/gloria/_components/tag/index.pug +17 -0
- package/themes/umberto/layout/gloria/_components/tooltip-popover/_style.scss +194 -0
- package/themes/umberto/layout/gloria/_components/tooltip-popover/index.pug +38 -0
- package/themes/umberto/layout/gloria/_head/head-preloads.pug +32 -0
- package/themes/umberto/layout/gloria/{_partial → _head}/head.pug +8 -4
- package/themes/umberto/layout/gloria/_head/index.pug +1 -0
- package/themes/umberto/layout/gloria/_modules/algolia-search/_style.scss +202 -0
- package/themes/umberto/layout/gloria/_modules/algolia-search/_third-party.scss +1 -0
- package/themes/umberto/layout/gloria/_modules/algolia-search/index.pug +38 -0
- package/themes/umberto/layout/gloria/_modules/breadcrumbs/_style.scss +68 -0
- package/themes/umberto/layout/gloria/_modules/breadcrumbs/index.pug +18 -0
- package/themes/umberto/layout/gloria/_modules/footer/_style.scss +40 -0
- package/themes/umberto/layout/gloria/_modules/footer/index.pug +87 -0
- package/themes/umberto/layout/gloria/_modules/header/_style.scss +181 -0
- package/themes/umberto/layout/gloria/_modules/header/index.pug +70 -0
- package/themes/umberto/layout/gloria/_modules/header/nav-link.pug +19 -0
- package/themes/umberto/layout/gloria/_modules/header/nav-links.pug +11 -0
- package/themes/umberto/layout/gloria/_modules/header/nav-project-select-dropdown.pug +16 -0
- package/themes/umberto/layout/gloria/_modules/header/nav-suffix-links.pug +20 -0
- package/themes/umberto/layout/gloria/_modules/header-bar/_style.scss +56 -0
- package/themes/umberto/layout/gloria/_modules/header-bar/index.pug +40 -0
- package/themes/umberto/layout/gloria/_modules/header-legacy-warning/index.pug +11 -0
- package/themes/umberto/layout/gloria/_modules/header-nightly-info/index.pug +20 -0
- package/themes/umberto/layout/gloria/_modules/header-promobar/index.pug +18 -0
- package/themes/umberto/layout/gloria/_modules/index.pug +14 -0
- package/themes/umberto/layout/gloria/_modules/main/_style.scss +54 -0
- package/themes/umberto/layout/gloria/_modules/main/index.pug +10 -0
- package/themes/umberto/layout/gloria/_modules/mobile-nav/_style.scss +106 -0
- package/themes/umberto/layout/gloria/_modules/mobile-nav/index.pug +121 -0
- package/themes/umberto/layout/gloria/_modules/mobile-nav/slide-parts.pug +67 -0
- package/themes/umberto/layout/gloria/_modules/not-found/_style.scss +38 -0
- package/themes/umberto/layout/gloria/_modules/not-found/index.pug +16 -0
- package/themes/umberto/layout/gloria/_modules/sidebar/_style.scss +147 -0
- package/themes/umberto/layout/gloria/_modules/sidebar/index.pug +24 -0
- package/themes/umberto/layout/gloria/_modules/sidebar-api/_style.scss +2 -0
- package/themes/umberto/layout/gloria/_modules/sidebar-api/index.pug +6 -0
- package/themes/umberto/layout/gloria/_modules/toc/_style.scss +201 -0
- package/themes/umberto/layout/gloria/_modules/toc/index.pug +10 -0
- package/themes/umberto/layout/gloria/_trackers/google-tag-manager.pug +14 -0
- package/themes/umberto/layout/gloria/_trackers/index.pug +2 -0
- package/themes/umberto/layout/gloria/api.pug +43 -20
- package/themes/umberto/layout/gloria/base.pug +23 -32
- package/themes/umberto/layout/gloria/index.pug +19 -13
- package/themes/umberto/layout/gloria/page.pug +30 -11
- package/themes/umberto/layout/gloria/sdk.pug +1 -1
- package/themes/umberto/layout/gloria/theme.pug +304 -0
- package/themes/umberto/layout/umberto/404.pug +0 -1
- package/themes/umberto/layout/umberto/_partial/report-issue-widget.pug +0 -3
- package/themes/umberto/source/gloria/assets/_fonts/Menlo/Menlo-Regular.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Menlo/Menlo-Regular.woff +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/Mulish-Italic-VariableFont_wght.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/Mulish-Italic-VariableFont_wght.woff2 +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/Mulish-VariableFont_wght.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/Mulish-VariableFont_wght.woff2 +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-Black.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-BlackItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-Bold.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-BoldItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-ExtraBold.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-ExtraBoldItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-ExtraLight.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-ExtraLightItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-Italic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-Light.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-LightItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-Medium.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-MediumItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-Regular.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-SemiBold.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Mulish/static/Mulish-SemiBoldItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/PublicSans-Italic-VariableFont_wght.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/PublicSans-Italic-VariableFont_wght.woff2 +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/PublicSans-VariableFont_wght.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/PublicSans-VariableFont_wght.woff2 +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-Black.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-BlackItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-Bold.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-BoldItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-ExtraBold.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-ExtraBoldItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-ExtraLight.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-ExtraLightItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-Italic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-Light.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-LightItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-Medium.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-MediumItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-Regular.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-SemiBold.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-SemiBoldItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-Thin.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_fonts/Public_Sans/static/PublicSans-ThinItalic.ttf +0 -0
- package/themes/umberto/source/gloria/assets/_img/404-billboard.svg +181 -0
- package/themes/umberto/source/gloria/assets/_img/ckeditor-logo.svg +15 -0
- package/themes/umberto/source/gloria/assets/_img/hex-bg-2.svg +10 -0
- package/themes/umberto/source/gloria/assets/_img/hex-bg.svg +10 -0
- package/themes/umberto/source/gloria/assets/_img/icons/api-class.svg +10 -0
- package/themes/umberto/source/gloria/assets/_img/icons/api-folder.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/api-interface.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/api-module.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/api-package.svg +4 -0
- package/themes/umberto/source/gloria/assets/_img/icons/api-typedef.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/bulb.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/check-circle.svg +4 -0
- package/themes/umberto/source/gloria/assets/_img/icons/check.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/chevron-down.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/chevron-right.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/close-circle.svg +4 -0
- package/themes/umberto/source/gloria/assets/_img/icons/close.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/copy.svg +10 -0
- package/themes/umberto/source/gloria/assets/_img/icons/dislike.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/download.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/edit.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/exclamation-circle.svg +4 -0
- package/themes/umberto/source/gloria/assets/_img/icons/experiment.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/export.svg +4 -0
- package/themes/umberto/source/gloria/assets/_img/icons/eye.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/filter.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/github.svg +10 -0
- package/themes/umberto/source/gloria/assets/_img/icons/info-circle.svg +4 -0
- package/themes/umberto/source/gloria/assets/_img/icons/like.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/link.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/lock.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/menu-fold.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/menu-list.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/menu.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/more.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/notification.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/number.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/premium.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/right.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/search.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/status.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/trash.svg +3 -0
- package/themes/umberto/source/gloria/assets/_img/icons/unordered-list.svg +5 -0
- package/themes/umberto/source/gloria/assets/_img/icons/warning.svg +10 -0
- package/themes/umberto/src/gloria/css/_fonts.scss +51 -0
- package/themes/umberto/src/gloria/css/_layers.scss +1 -0
- package/themes/umberto/src/gloria/css/_normalize.scss +118 -0
- package/themes/umberto/src/gloria/css/a11y/_focusable.scss +7 -0
- package/themes/umberto/src/gloria/css/a11y/_index.scss +4 -0
- package/themes/umberto/src/gloria/css/a11y/_mixins.scss +32 -0
- package/themes/umberto/src/gloria/css/a11y/_reduce-motion.scss +9 -0
- package/themes/umberto/src/gloria/css/a11y/_screen-reader.scss +15 -0
- package/themes/umberto/src/gloria/css/base/_buttons.scss +13 -0
- package/themes/umberto/src/gloria/css/base/_descriptions-list.scss +33 -0
- package/themes/umberto/src/gloria/css/base/_details.scss +7 -0
- package/themes/umberto/src/gloria/css/base/_headings.scss +111 -0
- package/themes/umberto/src/gloria/css/base/_iframes.scss +7 -0
- package/themes/umberto/src/gloria/css/base/_index.scss +12 -0
- package/themes/umberto/src/gloria/css/base/_inline-code.scss +15 -0
- package/themes/umberto/src/gloria/css/base/_links.scss +30 -0
- package/themes/umberto/src/gloria/css/base/_lists.scss +58 -0
- package/themes/umberto/src/gloria/css/base/_mixins.scss +3 -0
- package/themes/umberto/src/gloria/css/base/_paragraphs.scss +15 -0
- package/themes/umberto/src/gloria/css/base/_tables.scss +68 -0
- package/themes/umberto/src/gloria/css/base/_typography.scss +62 -0
- package/themes/umberto/src/gloria/css/components/_api-collapsing-list.scss +148 -0
- package/themes/umberto/src/gloria/css/components/_api-filter-dropdown.scss +17 -0
- package/themes/umberto/src/gloria/css/components/_api-item-heading.scss +58 -0
- package/themes/umberto/src/gloria/css/components/_api-tree.scss +202 -0
- package/themes/umberto/src/gloria/css/components/_hierarchy-list.scss +35 -0
- package/themes/umberto/src/gloria/css/components/_image-zoom.scss +13 -0
- package/themes/umberto/src/gloria/css/components/_index.scss +55 -0
- package/themes/umberto/src/gloria/css/components/_notification.scss +36 -0
- package/themes/umberto/src/gloria/css/components/_utils.scss +5 -0
- package/themes/umberto/src/gloria/css/doc/_details.scss +11 -0
- package/themes/umberto/src/gloria/css/doc/_editor-icons.scss +21 -0
- package/themes/umberto/src/gloria/css/doc/_images.scss +9 -0
- package/themes/umberto/src/gloria/css/doc/_index.scss +5 -0
- package/themes/umberto/src/gloria/css/doc/_snippets.scss +126 -0
- package/themes/umberto/src/gloria/css/doc/_typography.scss +5 -0
- package/themes/umberto/src/gloria/css/layout/_base.scss +27 -0
- package/themes/umberto/src/gloria/css/layout/_breakpoints.scss +88 -0
- package/themes/umberto/src/gloria/css/layout/_container.scss +38 -0
- package/themes/umberto/src/gloria/css/layout/_index.scss +6 -0
- package/themes/umberto/src/gloria/css/layout/_layout.scss +64 -0
- package/themes/umberto/src/gloria/css/layout/_mixins.scss +34 -0
- package/themes/umberto/src/gloria/css/layout/_zindex.scss +12 -0
- package/themes/umberto/src/gloria/css/modules/_index.scss +29 -0
- package/themes/umberto/src/gloria/css/modules/_utils.scss +7 -0
- package/themes/umberto/src/gloria/css/styles.scss +11 -117
- package/themes/umberto/src/gloria/css/theme/_light.scss +344 -0
- package/themes/umberto/src/gloria/css/utilities/_animation.scss +32 -0
- package/themes/umberto/src/gloria/css/utilities/_colors.scss +14 -0
- package/themes/umberto/src/gloria/css/utilities/_display.scss +13 -0
- package/themes/umberto/src/gloria/css/utilities/_flex.scss +33 -0
- package/themes/umberto/src/gloria/css/utilities/_gap.scss +8 -0
- package/themes/umberto/src/gloria/css/utilities/_index.scss +11 -0
- package/themes/umberto/src/gloria/css/utilities/_radius.scss +21 -0
- package/themes/umberto/src/gloria/css/utilities/_rotation.scss +8 -0
- package/themes/umberto/src/gloria/css/utilities/_shadows.scss +13 -0
- package/themes/umberto/src/gloria/css/utilities/_spacing.scss +96 -0
- package/themes/umberto/src/gloria/css/utilities/_stop-scrolling.scss +9 -0
- package/themes/umberto/src/gloria/css/utilities/_text.scss +42 -0
- package/themes/umberto/src/gloria/js/app.js +92 -54
- package/themes/umberto/src/gloria/js/components/api-nav-tree.js +171 -0
- package/themes/umberto/src/gloria/js/components/api-toggle.js +92 -0
- package/themes/umberto/src/gloria/js/components/base-component.js +41 -0
- package/themes/umberto/src/gloria/js/components/breadcrumbs.js +115 -0
- package/themes/umberto/src/gloria/js/components/code-block.js +226 -0
- package/themes/umberto/src/gloria/js/components/code-switcher.js +177 -0
- package/themes/umberto/src/gloria/js/components/dropdown.js +516 -0
- package/themes/umberto/src/gloria/js/components/expandable.js +79 -0
- package/themes/umberto/src/gloria/js/components/fake-devtools.js +722 -0
- package/themes/umberto/src/gloria/js/components/hash-link.js +60 -0
- package/themes/umberto/src/gloria/js/components/heading-link.js +135 -0
- package/themes/umberto/src/gloria/js/components/iframe.js +158 -0
- package/themes/umberto/src/gloria/js/{_imageModal.js → components/image-zoom.js} +1 -1
- package/themes/umberto/src/gloria/js/components/mobile-overlay.js +315 -0
- package/themes/umberto/src/gloria/js/components/nav-tree.js +164 -0
- package/themes/umberto/src/gloria/js/components/tabs.js +284 -0
- package/themes/umberto/src/gloria/js/components/tooltip-popover.js +576 -0
- package/themes/umberto/src/gloria/js/helpers/after-dom-ready.js +16 -0
- package/themes/umberto/src/gloria/js/helpers/animate-element.js +78 -0
- package/themes/umberto/src/gloria/js/helpers/body-scroll.js +22 -0
- package/themes/umberto/src/gloria/js/helpers/clamp.js +16 -0
- package/themes/umberto/src/gloria/js/helpers/classnames.js +64 -0
- package/themes/umberto/src/gloria/js/helpers/copy-to-clipboard.js +19 -0
- package/themes/umberto/src/gloria/js/helpers/create-anchor-positioning-watcher.js +46 -0
- package/themes/umberto/src/gloria/js/helpers/create-cleanup-registry.js +88 -0
- package/themes/umberto/src/gloria/js/helpers/create-hover-manager.js +93 -0
- package/themes/umberto/src/gloria/js/helpers/create-keyboard-blur-watcher.js +90 -0
- package/themes/umberto/src/gloria/js/helpers/create-keyboard-focus-cycler.js +251 -0
- package/themes/umberto/src/gloria/js/helpers/create-mutation-observer.js +49 -0
- package/themes/umberto/src/gloria/js/helpers/create-outside-click-watcher.js +39 -0
- package/themes/umberto/src/gloria/js/helpers/cubic-bezier.js +55 -0
- package/themes/umberto/src/gloria/js/helpers/date-time.js +21 -0
- package/themes/umberto/src/gloria/js/helpers/decode-html-entities.js +23 -0
- package/themes/umberto/src/gloria/js/helpers/escape-handler.js +59 -0
- package/themes/umberto/src/gloria/js/helpers/fetch-stylesheet.js +25 -0
- package/themes/umberto/src/gloria/js/helpers/find-code-lang.js +85 -0
- package/themes/umberto/src/gloria/js/helpers/focus-first-interactive.js +50 -0
- package/themes/umberto/src/gloria/js/helpers/format-html.js +181 -0
- package/themes/umberto/src/gloria/js/helpers/get-all-scrollable-parents.js +34 -0
- package/themes/umberto/src/gloria/js/helpers/get-parents-until.js +26 -0
- package/themes/umberto/src/gloria/js/helpers/highlight-code.js +18 -0
- package/themes/umberto/src/gloria/js/helpers/html-builder.js +69 -0
- package/themes/umberto/src/gloria/js/helpers/identity.js +8 -0
- package/themes/umberto/src/gloria/js/helpers/inject-resource-preload.js +51 -0
- package/themes/umberto/src/gloria/js/helpers/inject-script.js +79 -0
- package/themes/umberto/src/gloria/js/helpers/inject-stylesheet.js +108 -0
- package/themes/umberto/src/gloria/js/helpers/is-element-attached.js +28 -0
- package/themes/umberto/src/gloria/js/helpers/is-focusable.js +14 -0
- package/themes/umberto/src/gloria/js/helpers/is-hidden-element.js +8 -0
- package/themes/umberto/src/gloria/js/helpers/is-mobile.js +8 -0
- package/themes/umberto/src/gloria/js/helpers/is-unsafe-key.js +14 -0
- package/themes/umberto/src/gloria/js/helpers/lerp.js +27 -0
- package/themes/umberto/src/gloria/js/helpers/local-storage-helper.js +133 -0
- package/themes/umberto/src/gloria/js/helpers/pipe.js +8 -0
- package/themes/umberto/src/gloria/js/helpers/prefers-reduced-motion.js +13 -0
- package/themes/umberto/src/gloria/js/helpers/random-id.js +51 -0
- package/themes/umberto/src/gloria/js/helpers/sanitize-text.js +27 -0
- package/themes/umberto/src/gloria/js/helpers/scroll-to-hash.js +31 -0
- package/themes/umberto/src/gloria/js/helpers/take-last.js +19 -0
- package/themes/umberto/src/gloria/js/helpers/tap.js +11 -0
- package/themes/umberto/src/gloria/js/helpers/throttle.js +46 -0
- package/themes/umberto/src/gloria/js/helpers/timeout.js +14 -0
- package/themes/umberto/src/gloria/js/helpers/toggle-height.js +46 -0
- package/themes/umberto/src/gloria/js/helpers/tween.js +100 -0
- package/themes/umberto/src/gloria/js/helpers/wrap-around.js +39 -0
- package/themes/umberto/src/gloria/js/modules/algolia-search.js +168 -0
- package/themes/umberto/src/gloria/js/modules/api-filter.js +184 -0
- package/themes/umberto/src/gloria/js/modules/header-bar.js +154 -0
- package/themes/umberto/src/gloria/js/modules/header.js +242 -0
- package/themes/umberto/src/gloria/js/modules/links-prefetch.js +196 -0
- package/themes/umberto/src/gloria/js/modules/mobile-nav.js +327 -0
- package/themes/umberto/src/gloria/js/modules/sidebar.js +114 -0
- package/themes/umberto/src/gloria/js/modules/table-of-contents-api.js +214 -0
- package/themes/umberto/src/gloria/js/modules/table-of-contents.js +287 -0
- package/themes/umberto/src/gloria/js/public-api.js +75 -0
- package/themes/umberto/src/gloria/js/web-components/svg-icon.js +117 -0
- package/themes/umberto/src/umberto/js/_codeswitcherbuttons.js +1 -1
- package/themes/umberto/layout/gloria/_api-docs/_mixin/_api-title.pug +0 -17
- package/themes/umberto/layout/gloria/_mixin/nav-tree-item.pug +0 -13
- package/themes/umberto/layout/gloria/_partial/docsearch.pug +0 -21
- package/themes/umberto/layout/gloria/_partial/dropdown.pug +0 -12
- package/themes/umberto/layout/gloria/_partial/feedback-widget.pug +0 -20
- package/themes/umberto/layout/gloria/_partial/footer.pug +0 -6
- package/themes/umberto/layout/gloria/_partial/gh-contribute.pug +0 -8
- package/themes/umberto/layout/gloria/_partial/google-tag-manager.pug +0 -18
- package/themes/umberto/layout/gloria/_partial/header.pug +0 -64
- package/themes/umberto/layout/gloria/_partial/nav-tree.pug +0 -9
- package/themes/umberto/layout/gloria/_partial/report-issue-widget.pug +0 -26
- package/themes/umberto/layout/gloria/_partial/rwd-breadcrumbs.pug +0 -13
- package/themes/umberto/layout/gloria/_partial/search-box.pug +0 -6
- package/themes/umberto/layout/gloria/_partial/vwo.pug +0 -11
- package/themes/umberto/source/gloria/assets/_img/arrows.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/book.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/box-brown.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/box-orange.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/box-red.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/bulb.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/clipboard.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/cog.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/data.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/documentation.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/download.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/edit.svg +0 -2
- package/themes/umberto/source/gloria/assets/_img/exclamation-circle.svg +0 -2
- package/themes/umberto/source/gloria/assets/_img/eye.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/filter.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/filtering.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/folder.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/github.svg +0 -6
- package/themes/umberto/source/gloria/assets/_img/header-info-configs.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/header-info-events.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/header-info-methods.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/header-info-properties.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/heart.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/info-circle.svg +0 -4
- package/themes/umberto/source/gloria/assets/_img/info.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/list-nest.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/loupe.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/menu.svg +0 -4
- package/themes/umberto/source/gloria/assets/_img/plug.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/star-in-circle.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/tick.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/triangle-down.svg +0 -1
- package/themes/umberto/source/gloria/assets/_img/triangle-right.svg +0 -1
- package/themes/umberto/src/gloria/css/_api-content.scss +0 -32
- package/themes/umberto/src/gloria/css/_api-info-box.scss +0 -86
- package/themes/umberto/src/gloria/css/_api-props-filter.scss +0 -106
- package/themes/umberto/src/gloria/css/_api-see-source.scss +0 -35
- package/themes/umberto/src/gloria/css/_api-subheader.scss +0 -167
- package/themes/umberto/src/gloria/css/_api-tree.scss +0 -121
- package/themes/umberto/src/gloria/css/_badge.scss +0 -74
- package/themes/umberto/src/gloria/css/_code-switcher.scss +0 -61
- package/themes/umberto/src/gloria/css/_collapsinglist.scss +0 -262
- package/themes/umberto/src/gloria/css/_content.scss +0 -236
- package/themes/umberto/src/gloria/css/_docsearch.scss +0 -109
- package/themes/umberto/src/gloria/css/_dropdown.scss +0 -63
- package/themes/umberto/src/gloria/css/_editor-icon.scss +0 -26
- package/themes/umberto/src/gloria/css/_feedback-widget.scss +0 -11
- package/themes/umberto/src/gloria/css/_font-external.scss +0 -8
- package/themes/umberto/src/gloria/css/_footer.scss +0 -40
- package/themes/umberto/src/gloria/css/_formatted.scss +0 -285
- package/themes/umberto/src/gloria/css/_guide-content.scss +0 -37
- package/themes/umberto/src/gloria/css/_guide-sdk-tree.scss +0 -14
- package/themes/umberto/src/gloria/css/_loading-spinner.scss +0 -33
- package/themes/umberto/src/gloria/css/_main.scss +0 -59
- package/themes/umberto/src/gloria/css/_navigation.scss +0 -35
- package/themes/umberto/src/gloria/css/_notice.scss +0 -116
- package/themes/umberto/src/gloria/css/_print.scss +0 -20
- package/themes/umberto/src/gloria/css/_prism.scss +0 -223
- package/themes/umberto/src/gloria/css/_rwd-breadcrumbs.scss +0 -28
- package/themes/umberto/src/gloria/css/_rwd-menu.scss +0 -89
- package/themes/umberto/src/gloria/css/_secondary-navigation.scss +0 -152
- package/themes/umberto/src/gloria/css/_theme-dark.scss +0 -175
- package/themes/umberto/src/gloria/css/_toggler.scss +0 -46
- package/themes/umberto/src/gloria/css/_top.scss +0 -350
- package/themes/umberto/src/gloria/css/_tree.scss +0 -218
- package/themes/umberto/src/gloria/css/_warning-banner.scss +0 -46
- package/themes/umberto/src/gloria/css/components/_lightbox.scss +0 -12
- package/themes/umberto/src/gloria/css/helpers/_color.scss +0 -49
- package/themes/umberto/src/gloria/css/helpers/_font.scss +0 -60
- package/themes/umberto/src/gloria/css/helpers/_globals.scss +0 -129
- package/themes/umberto/src/gloria/css/helpers/_reset.scss +0 -52
- package/themes/umberto/src/gloria/css/helpers/_spacing.scss +0 -21
- package/themes/umberto/src/gloria/css/pages/_sdk.scss +0 -111
- package/themes/umberto/src/gloria/js/_anchors.js +0 -57
- package/themes/umberto/src/gloria/js/_apisearch.js +0 -126
- package/themes/umberto/src/gloria/js/_apitree.js +0 -67
- package/themes/umberto/src/gloria/js/_attachpermalinklistener.js +0 -50
- package/themes/umberto/src/gloria/js/_codeswitcherbuttons.js +0 -146
- package/themes/umberto/src/gloria/js/_collapsables.js +0 -135
- package/themes/umberto/src/gloria/js/_copymobileapinavigation.js +0 -26
- package/themes/umberto/src/gloria/js/_devnames.js +0 -37
- package/themes/umberto/src/gloria/js/_dropdowns.js +0 -55
- package/themes/umberto/src/gloria/js/_filtering.js +0 -139
- package/themes/umberto/src/gloria/js/_pagenavigation.js +0 -93
- package/themes/umberto/src/gloria/js/_prism.js +0 -104
- package/themes/umberto/src/gloria/js/_rwdmenu.js +0 -15
- package/themes/umberto/src/gloria/js/_samplecode.js +0 -23
- package/themes/umberto/src/gloria/js/_sidenavigation.js +0 -59
- package/themes/umberto/src/gloria/js/_toc.js +0 -93
- package/themes/umberto/src/gloria/js/_tooltips.js +0 -39
- package/themes/umberto/src/gloria/js/_warningbanner.js +0 -18
- package/themes/umberto/src/gloria/js/vendor/prism.js +0 -45
- /package/themes/umberto/layout/gloria/_api-docs/_partial/{api-info-box.pug → api-hierarchy.pug} +0 -0
- /package/themes/umberto/layout/gloria/{_partial → _trackers}/google-analytics.pug +0 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { BaseComponent } from './base-component';
|
|
7
|
+
import { createOutsideClickWatcher } from '../helpers/create-outside-click-watcher';
|
|
8
|
+
import { createKeyboardFocusCycler, getVerticalKeysMap } from '../helpers/create-keyboard-focus-cycler';
|
|
9
|
+
import { createKeyboardBlurWatcher } from '../helpers/create-keyboard-blur-watcher';
|
|
10
|
+
import { onEscapeKeyPress } from '../helpers/escape-handler';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A dropdown component that manages togglable dropdown menus with automatic positioning.
|
|
14
|
+
* Handles opening, closing, and optimal positioning based on available screen space.
|
|
15
|
+
*/
|
|
16
|
+
export class Dropdown extends BaseComponent {
|
|
17
|
+
/**
|
|
18
|
+
* Creates a dropdown component.
|
|
19
|
+
*
|
|
20
|
+
* @param wrapper - The dropdown container element.
|
|
21
|
+
*/
|
|
22
|
+
constructor( wrapper ) {
|
|
23
|
+
super( {
|
|
24
|
+
isOpen: false,
|
|
25
|
+
position: 'bottom',
|
|
26
|
+
horizontalOffset: 0,
|
|
27
|
+
selectedValue: null,
|
|
28
|
+
updateValueOnSelect: wrapper.hasAttribute( 'data-update-value-on-select' )
|
|
29
|
+
} );
|
|
30
|
+
|
|
31
|
+
const trigger = wrapper.querySelector( '[aria-haspopup="true"][aria-expanded][aria-controls]' );
|
|
32
|
+
const content = document.getElementById( trigger.getAttribute( 'aria-controls' ) );
|
|
33
|
+
|
|
34
|
+
this.elements = {
|
|
35
|
+
wrapper,
|
|
36
|
+
trigger,
|
|
37
|
+
content,
|
|
38
|
+
items: [ ...content.querySelectorAll( '.c-dropdown__item' ) ]
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// Get initial selected value from active item or trigger
|
|
42
|
+
this.state.selectedValue = this.findInitialSelectedValue();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Initializes all dropdown components on the page.
|
|
47
|
+
*/
|
|
48
|
+
static attach() {
|
|
49
|
+
const dropdowns = document.querySelectorAll( '.c-dropdown:has(button[aria-haspopup])' );
|
|
50
|
+
|
|
51
|
+
for ( const element of dropdowns ) {
|
|
52
|
+
element.dropdown = new Dropdown( element ).init();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Initializes the dropdown component with event listeners.
|
|
58
|
+
*/
|
|
59
|
+
init() {
|
|
60
|
+
this.elements.trigger.addEventListener( 'click', () => {
|
|
61
|
+
if ( !this.state.isOpen ) {
|
|
62
|
+
this.determinePosition();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.setState( { isOpen: !this.state.isOpen } );
|
|
66
|
+
} );
|
|
67
|
+
|
|
68
|
+
for ( const item of this.elements.items ) {
|
|
69
|
+
item.addEventListener( 'click', event => {
|
|
70
|
+
if ( this.state.updateValueOnSelect ) {
|
|
71
|
+
event.preventDefault();
|
|
72
|
+
this.setSelectedItem( item );
|
|
73
|
+
}
|
|
74
|
+
} );
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
this.determinePosition();
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Finds the initial selected value from active item or trigger text.
|
|
83
|
+
*
|
|
84
|
+
* @returns The initial selected value.
|
|
85
|
+
*/
|
|
86
|
+
findInitialSelectedValue() {
|
|
87
|
+
const activeItem = this.elements.items.find( item => item.classList.contains( 'is-active' ) );
|
|
88
|
+
|
|
89
|
+
if ( activeItem ) {
|
|
90
|
+
return getItemValue( activeItem );
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Fall back to trigger text content
|
|
94
|
+
return this.elements.trigger.textContent?.trim() || null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Handles selection of a dropdown item.
|
|
99
|
+
*
|
|
100
|
+
* @param item - The selected dropdown item.
|
|
101
|
+
*/
|
|
102
|
+
setSelectedItem( item ) {
|
|
103
|
+
const value = getItemValue( item );
|
|
104
|
+
const prevSelectedValue = this.state.selectedValue;
|
|
105
|
+
|
|
106
|
+
// Update state
|
|
107
|
+
this.setState( {
|
|
108
|
+
selectedValue: value,
|
|
109
|
+
isOpen: false
|
|
110
|
+
} );
|
|
111
|
+
|
|
112
|
+
// Update trigger text if enabled
|
|
113
|
+
if ( this.state.updateValueOnSelect ) {
|
|
114
|
+
this.updateTriggerText( item );
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Dispatch custom event
|
|
118
|
+
this.dispatchSelectionEvent( value, prevSelectedValue, item );
|
|
119
|
+
|
|
120
|
+
// Return focus to trigger
|
|
121
|
+
this.elements.trigger.focus();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Attaches a listener to the dropdown selection event.
|
|
126
|
+
*/
|
|
127
|
+
onSelectedItem( callback ) {
|
|
128
|
+
onDropdownSelection( this.elements.wrapper, callback );
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Updates the trigger button text with selected item content.
|
|
133
|
+
*
|
|
134
|
+
* @param selectedItem - The selected dropdown item.
|
|
135
|
+
*/
|
|
136
|
+
updateTriggerText( selectedItem ) {
|
|
137
|
+
const { trigger } = this.elements;
|
|
138
|
+
|
|
139
|
+
const triggerTextElement = trigger.querySelector( '.c-button__label' );
|
|
140
|
+
const itemTextContent = selectedItem.textContent?.trim();
|
|
141
|
+
|
|
142
|
+
if ( !itemTextContent || !triggerTextElement ) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
triggerTextElement.textContent = itemTextContent;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Dispatches a custom selection event.
|
|
151
|
+
*
|
|
152
|
+
* @param value - The selected value.
|
|
153
|
+
* @param previousValue - The previously selected value.
|
|
154
|
+
* @param item - The selected item element.
|
|
155
|
+
*/
|
|
156
|
+
dispatchSelectionEvent( value, previousValue, item ) {
|
|
157
|
+
const selectionEvent = new CustomEvent( 'dropdown:select', {
|
|
158
|
+
bubbles: true,
|
|
159
|
+
detail: {
|
|
160
|
+
value,
|
|
161
|
+
previousValue,
|
|
162
|
+
item,
|
|
163
|
+
dropdown: this
|
|
164
|
+
}
|
|
165
|
+
} );
|
|
166
|
+
|
|
167
|
+
this.elements.wrapper.dispatchEvent( selectionEvent );
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Renders the dropdown based on current state.
|
|
172
|
+
*
|
|
173
|
+
* @param prevState - Previous component state.
|
|
174
|
+
* @param state - Current component state.
|
|
175
|
+
*/
|
|
176
|
+
render( prevState = undefined, state = this.state ) {
|
|
177
|
+
const { content, trigger } = this.elements;
|
|
178
|
+
const { position, isOpen, horizontalOffset, selectedValue } = state;
|
|
179
|
+
|
|
180
|
+
// Update active states when selectedValue changes
|
|
181
|
+
if ( prevState && prevState.selectedValue !== selectedValue ) {
|
|
182
|
+
this.elements.items.forEach( item => {
|
|
183
|
+
const itemValue = getItemValue( item );
|
|
184
|
+
|
|
185
|
+
item.classList.toggle( 'is-active', itemValue === selectedValue );
|
|
186
|
+
} );
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Toggle dropdown position classes.
|
|
190
|
+
content.classList.remove(
|
|
191
|
+
'c-dropdown__content--position-top',
|
|
192
|
+
'c-dropdown__content--position-bottom'
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
content.classList.add( `c-dropdown__content--position-${ position }` );
|
|
196
|
+
|
|
197
|
+
if ( isOpen && horizontalOffset !== 0 ) {
|
|
198
|
+
content.style.marginLeft = `${ horizontalOffset }px`;
|
|
199
|
+
} else {
|
|
200
|
+
content.style.marginLeft = '';
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Toggle dropdown visibility.
|
|
204
|
+
content.classList.toggle( 'c-dropdown__content--open', isOpen );
|
|
205
|
+
|
|
206
|
+
if ( !content.getAttribute( 'style' ) ) {
|
|
207
|
+
content.removeAttribute( 'style' );
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Toggle aria attributes for accessibility.
|
|
211
|
+
content.setAttribute( 'aria-hidden', !isOpen );
|
|
212
|
+
trigger.setAttribute( 'aria-expanded', isOpen );
|
|
213
|
+
|
|
214
|
+
// Toggle activity classes on button within the trigger.
|
|
215
|
+
if ( trigger.classList.contains( 'c-button' ) ) {
|
|
216
|
+
trigger.classList.toggle( 'is-active', isOpen );
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Set proper global listeners.
|
|
220
|
+
if ( prevState && prevState.isOpen !== isOpen ) {
|
|
221
|
+
// Clean up previous listeners
|
|
222
|
+
this.outsideClickCleanup?.();
|
|
223
|
+
this.outsideClickCleanup = null;
|
|
224
|
+
|
|
225
|
+
this.keyboardFocusCyclerWatcherCleanup?.();
|
|
226
|
+
this.keyboardFocusCyclerWatcherCleanup = null;
|
|
227
|
+
|
|
228
|
+
this.keyboardBlurCleanup?.();
|
|
229
|
+
this.keyboardBlurCleanup = null;
|
|
230
|
+
|
|
231
|
+
// Set up listeners if dropdown is open
|
|
232
|
+
if ( isOpen ) {
|
|
233
|
+
this.setupOutsideClickWatcher();
|
|
234
|
+
this.setupKeyboardFocusCyclerWatcher();
|
|
235
|
+
this.setupKeyboardBlurWatcher();
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Calculates the optimal position for the dropdown.
|
|
242
|
+
*/
|
|
243
|
+
determinePosition() {
|
|
244
|
+
const { trigger, content, wrapper } = this.elements;
|
|
245
|
+
const preferredDirection = wrapper.dataset.preferredDirection;
|
|
246
|
+
|
|
247
|
+
const contentRect = measureDropdownRect( content );
|
|
248
|
+
const availableSpace = getAvailableSpace( trigger );
|
|
249
|
+
|
|
250
|
+
const { position, horizontalOffset } = determineDropdownPosition(
|
|
251
|
+
availableSpace,
|
|
252
|
+
contentRect,
|
|
253
|
+
preferredDirection
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
this.setState( { position, horizontalOffset } );
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Sets up the keyboard focus cycling for dropdown items.
|
|
261
|
+
*/
|
|
262
|
+
setupKeyboardFocusCyclerWatcher() {
|
|
263
|
+
const keyMap = getVerticalKeysMap();
|
|
264
|
+
const { position } = this.state;
|
|
265
|
+
|
|
266
|
+
const focusCycler = createKeyboardFocusCycler( {
|
|
267
|
+
keyMap,
|
|
268
|
+
items: this.elements.items,
|
|
269
|
+
focusElements: true,
|
|
270
|
+
onFocusEnter: item => item.classList.add( 'is-highlighted' ),
|
|
271
|
+
onFocusLeave: item => item.classList.remove( 'is-highlighted' )
|
|
272
|
+
} );
|
|
273
|
+
|
|
274
|
+
// Handle case when user presses arrow keys to focus first item.
|
|
275
|
+
const handleFocusFirstKeydown = event => {
|
|
276
|
+
if ( ![ 'ArrowUp', 'Up', 'ArrowDown', 'Down' ].includes( event.key ) ) {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
window.removeEventListener( 'keydown', handleFocusFirstKeydown );
|
|
281
|
+
event.preventDefault();
|
|
282
|
+
|
|
283
|
+
switch ( position ) {
|
|
284
|
+
case 'top':
|
|
285
|
+
if ( event.key === 'ArrowUp' || event.key === 'Up' ) {
|
|
286
|
+
focusCycler.activateLast();
|
|
287
|
+
} else {
|
|
288
|
+
focusCycler.activateFirst();
|
|
289
|
+
}
|
|
290
|
+
break;
|
|
291
|
+
|
|
292
|
+
case 'bottom':
|
|
293
|
+
if ( event.key === 'ArrowDown' || event.key === 'Down' ) {
|
|
294
|
+
focusCycler.activateFirst();
|
|
295
|
+
} else {
|
|
296
|
+
focusCycler.activateLast();
|
|
297
|
+
}
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
// Handle case when user presses Escape to close the dropdown.
|
|
303
|
+
const unmountEscapeHandler = onEscapeKeyPress( () => {
|
|
304
|
+
this.setState( { isOpen: false } );
|
|
305
|
+
this.elements.trigger.focus();
|
|
306
|
+
} );
|
|
307
|
+
|
|
308
|
+
window.addEventListener( 'keydown', handleFocusFirstKeydown );
|
|
309
|
+
|
|
310
|
+
this.keyboardFocusCyclerWatcherCleanup = () => {
|
|
311
|
+
window.removeEventListener( 'keydown', handleFocusFirstKeydown );
|
|
312
|
+
unmountEscapeHandler();
|
|
313
|
+
focusCycler.unmount();
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Sets up the outside click watcher to close the dropdown.
|
|
319
|
+
*/
|
|
320
|
+
setupOutsideClickWatcher() {
|
|
321
|
+
this.outsideClickCleanup = createOutsideClickWatcher( {
|
|
322
|
+
elements: [ this.elements.content, this.elements.trigger ],
|
|
323
|
+
callback: () => this.setState( { isOpen: false } )
|
|
324
|
+
} );
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Sets up a watcher to close dropdown when focus moves outside both trigger and content.
|
|
329
|
+
*/
|
|
330
|
+
setupKeyboardBlurWatcher() {
|
|
331
|
+
this.keyboardBlurCleanup = createKeyboardBlurWatcher( {
|
|
332
|
+
elements: [ this.elements.trigger, this.elements.content ],
|
|
333
|
+
callback: () => this.setState( { isOpen: false } )
|
|
334
|
+
} );
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Measures dimensions of the dropdown content element.
|
|
340
|
+
*
|
|
341
|
+
* @param content - The dropdown content element.
|
|
342
|
+
* @returns The dimensions of the content.
|
|
343
|
+
*/
|
|
344
|
+
function measureDropdownRect( content ) {
|
|
345
|
+
// Temporarily show the content to measure it.
|
|
346
|
+
content.style.visibility = 'hidden';
|
|
347
|
+
content.style.display = 'block';
|
|
348
|
+
|
|
349
|
+
const contentRect = content.getBoundingClientRect();
|
|
350
|
+
|
|
351
|
+
// Restore original styles.
|
|
352
|
+
content.style.display = '';
|
|
353
|
+
content.style.visibility = '';
|
|
354
|
+
|
|
355
|
+
return contentRect;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Calculates available space around the trigger element.
|
|
360
|
+
*
|
|
361
|
+
* @param trigger - The dropdown trigger element.
|
|
362
|
+
* @returns Object containing space measurements.
|
|
363
|
+
*/
|
|
364
|
+
function getAvailableSpace( trigger ) {
|
|
365
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
366
|
+
const viewportHeight = window.innerHeight;
|
|
367
|
+
const viewportWidth = window.innerWidth;
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
above: triggerRect.top,
|
|
371
|
+
below: viewportHeight - triggerRect.bottom,
|
|
372
|
+
left: triggerRect.left,
|
|
373
|
+
right: viewportWidth - triggerRect.right,
|
|
374
|
+
triggerRect,
|
|
375
|
+
viewportWidth
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Determines the optimal position for the dropdown based on available space.
|
|
381
|
+
*
|
|
382
|
+
* @param space - Available space measurements.
|
|
383
|
+
* @param contentRect - The dimensions of the content.
|
|
384
|
+
* @param preferredDirection - Preferred direction from data attribute.
|
|
385
|
+
* @returns Position information with vertical position and horizontal offset.
|
|
386
|
+
*/
|
|
387
|
+
function determineDropdownPosition( space, contentRect, preferredDirection ) {
|
|
388
|
+
const position = determineVerticalPosition( space, contentRect, preferredDirection );
|
|
389
|
+
const horizontalOffset = calculateHorizontalOffset( space, contentRect );
|
|
390
|
+
|
|
391
|
+
return { position, horizontalOffset };
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/**
|
|
395
|
+
* Determines the vertical position (top/bottom) for the dropdown.
|
|
396
|
+
*
|
|
397
|
+
* @param space - Available space measurements.
|
|
398
|
+
* @param contentRect - The dimensions of the content.
|
|
399
|
+
* @param preferredDirection - Preferred direction from data attribute.
|
|
400
|
+
* @returns The vertical position ('top' or 'bottom').
|
|
401
|
+
*/
|
|
402
|
+
function determineVerticalPosition( space, contentRect, preferredDirection ) {
|
|
403
|
+
const minRequiredVerticalSpace = contentRect.height + 10;
|
|
404
|
+
|
|
405
|
+
if ( preferredDirection === 'up' && space.above >= minRequiredVerticalSpace ) {
|
|
406
|
+
return 'top';
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if ( preferredDirection === 'down' && space.below >= minRequiredVerticalSpace ) {
|
|
410
|
+
return 'bottom';
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return ( space.below < minRequiredVerticalSpace ) ? 'top' : 'bottom';
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Calculates the horizontal offset to prevent screen overflow.
|
|
418
|
+
*
|
|
419
|
+
* @param space - Available space measurements.
|
|
420
|
+
* @param contentRect - The dimensions of the content.
|
|
421
|
+
* @returns The horizontal offset in pixels.
|
|
422
|
+
*/
|
|
423
|
+
function calculateHorizontalOffset( space, contentRect ) {
|
|
424
|
+
const { viewportWidth } = space;
|
|
425
|
+
|
|
426
|
+
const screenMargin = 5;
|
|
427
|
+
|
|
428
|
+
const contentLeft = contentRect.left;
|
|
429
|
+
const contentRight = contentRect.right;
|
|
430
|
+
|
|
431
|
+
// Check if dropdown overflows right side of screen.
|
|
432
|
+
if ( contentRight > viewportWidth ) {
|
|
433
|
+
const rightOverflow = contentRight - viewportWidth;
|
|
434
|
+
|
|
435
|
+
return -rightOverflow - screenMargin;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Check if dropdown overflows left side of screen.
|
|
439
|
+
if ( contentLeft < 0 ) {
|
|
440
|
+
return Math.abs( contentLeft ) + screenMargin;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return 0;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Gets the value from a dropdown item.
|
|
448
|
+
*
|
|
449
|
+
* @param item - The dropdown item element.
|
|
450
|
+
* @returns The item value.
|
|
451
|
+
*/
|
|
452
|
+
function getItemValue( item ) {
|
|
453
|
+
return item.dataset.itemId ||
|
|
454
|
+
item.dataset.value ||
|
|
455
|
+
item.textContent?.trim() ||
|
|
456
|
+
null;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Attaches a listener to the dropdown selection event.
|
|
461
|
+
*
|
|
462
|
+
* @param element - The element within a dropdown component that should listen for changes
|
|
463
|
+
* @param callback - Callback function to execute when selection changes
|
|
464
|
+
* @returns A cleanup function to remove the event listener
|
|
465
|
+
*/
|
|
466
|
+
export function onDropdownSelection( element, callback ) {
|
|
467
|
+
const handler = event => {
|
|
468
|
+
callback( event.detail );
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
// Find the closest dropdown container
|
|
472
|
+
const dropdownContainer = element.closest( '.c-dropdown' );
|
|
473
|
+
|
|
474
|
+
if ( !dropdownContainer ) {
|
|
475
|
+
throw new Error( 'Element is not inside a dropdown component' );
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
dropdownContainer.addEventListener( 'dropdown:select', handler );
|
|
479
|
+
|
|
480
|
+
return () => {
|
|
481
|
+
dropdownContainer.removeEventListener( 'dropdown:select', handler );
|
|
482
|
+
};
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Programmatically selects a dropdown item by value.
|
|
487
|
+
*
|
|
488
|
+
* @param element - An element within the dropdown component or the dropdown container itself
|
|
489
|
+
* @param value - The value to select (matches data-item-id, data-value, or text content)
|
|
490
|
+
* @returns Boolean indicating whether the selection was successful
|
|
491
|
+
*/
|
|
492
|
+
export function selectDropdownItem( element, value ) {
|
|
493
|
+
// Find the closest dropdown container
|
|
494
|
+
const dropdownContainer = element.closest( '.c-dropdown' ) ||
|
|
495
|
+
( element.classList.contains( 'c-dropdown' ) ? element : null );
|
|
496
|
+
|
|
497
|
+
if ( !dropdownContainer ) {
|
|
498
|
+
throw new Error( 'Element is not inside a dropdown component' );
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Find the item with matching value
|
|
502
|
+
const items = dropdownContainer.querySelectorAll( '.c-dropdown__item' );
|
|
503
|
+
const targetItem = Array.from( items ).find( item => {
|
|
504
|
+
const itemValue = getItemValue( item );
|
|
505
|
+
return itemValue === value;
|
|
506
|
+
} );
|
|
507
|
+
|
|
508
|
+
if ( !targetItem ) {
|
|
509
|
+
console.warn( `Dropdown item with value "${ value }" not found` );
|
|
510
|
+
return false;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Trigger a click on the item to select it
|
|
514
|
+
targetItem.click();
|
|
515
|
+
return true;
|
|
516
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license Copyright (c) 2017-2025, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
|
+
* For licensing, see LICENSE.md.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { BaseComponent } from './base-component';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Component for managing expandable/collapsible content sections.
|
|
10
|
+
* Tracks expanded state and manages accessibility attributes.
|
|
11
|
+
*/
|
|
12
|
+
export class Expandable extends BaseComponent {
|
|
13
|
+
/**
|
|
14
|
+
* Creates an expandable component.
|
|
15
|
+
*
|
|
16
|
+
* @param element - The expandable component wrapper element
|
|
17
|
+
*/
|
|
18
|
+
constructor( element ) {
|
|
19
|
+
super( {
|
|
20
|
+
expanded: false
|
|
21
|
+
} );
|
|
22
|
+
|
|
23
|
+
const trigger = element.querySelector( '[aria-controls]' );
|
|
24
|
+
const contentId = trigger.getAttribute( 'aria-controls' );
|
|
25
|
+
const content = document.getElementById( contentId );
|
|
26
|
+
|
|
27
|
+
this.elements = {
|
|
28
|
+
wrapper: element,
|
|
29
|
+
trigger,
|
|
30
|
+
content
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Creates expandable components for all matching elements on the page.
|
|
36
|
+
*/
|
|
37
|
+
static attach() {
|
|
38
|
+
const expandableElements = document.querySelectorAll( '.js-expandable' );
|
|
39
|
+
|
|
40
|
+
for ( const element of expandableElements ) {
|
|
41
|
+
new Expandable( element ).init();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Initializes the expandable component.
|
|
47
|
+
* Sets up event listeners for the trigger element.
|
|
48
|
+
*/
|
|
49
|
+
init() {
|
|
50
|
+
const { trigger } = this.elements;
|
|
51
|
+
|
|
52
|
+
// Add click handler to toggle expanded state
|
|
53
|
+
trigger.addEventListener( 'click', () => {
|
|
54
|
+
this.setState( { expanded: !this.state.expanded } );
|
|
55
|
+
} );
|
|
56
|
+
|
|
57
|
+
// Initialize ARIA attributes based on initial state
|
|
58
|
+
this.render();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Renders the component based on current state.
|
|
63
|
+
* Updates the visibility and accessibility attributes.
|
|
64
|
+
*
|
|
65
|
+
* @param prevState - Previous component state
|
|
66
|
+
* @param state - Current component state
|
|
67
|
+
*/
|
|
68
|
+
render( prevState, state = this.state ) {
|
|
69
|
+
const { trigger, content } = this.elements;
|
|
70
|
+
const { expanded } = state;
|
|
71
|
+
|
|
72
|
+
// Update ARIA attributes for accessibility
|
|
73
|
+
content.setAttribute( 'aria-hidden', !expanded );
|
|
74
|
+
trigger.setAttribute( 'aria-expanded', expanded );
|
|
75
|
+
|
|
76
|
+
// Toggle a visual class for styling
|
|
77
|
+
content.classList.toggle( 'is-expanded', expanded );
|
|
78
|
+
}
|
|
79
|
+
}
|