diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..32683aaba2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + versioning-strategy: increase diff --git a/.gitignore b/.gitignore index 19f09b11e1..67481116ba 100644 --- a/.gitignore +++ b/.gitignore @@ -41,12 +41,11 @@ Thumbs.db ###################### *.sublime-workspace -# Jekyll Site # +# 11ty Site # ############### # This is compiled by Netlify on its servers, so no need to include it. _site/ .asset-cache -.jekyll-metadata # Komodo Edit # ############### @@ -58,7 +57,9 @@ node_modules # Compiled CSS/JS # ############### -/dist/css/ +/dist/css/* +!/dist/css/stacks-flexgrid-shim.min.css +/dist/js/ /docs/assets/css/ /docs/assets/js/stacks.* /docs/assets/js/controllers.js @@ -80,6 +81,7 @@ node_modules # Testing Assets # ############### /backstop_data/bitmaps_test/ +/backstop_data/bitmaps_reference/ /backstop_data/html_report/ # GitHub Actions # diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000000..89ba921fc1 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,3 @@ +node_modules +*.* +!*.less \ No newline at end of file diff --git a/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000000..73ae294e88 --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,28 @@ +{ + "extends": "stylelint-config-recommended-less", + "customSyntax": "postcss-less", + "plugins": [ + "stylelint-less" + ], + "rules": { + "at-rule-no-unknown": null, + "less/color-no-invalid-hex": null, + "less/no-duplicate-variables": null, + "indentation": 4, + "max-empty-lines": 2, + "no-invalid-double-slash-comments": null, + "rule-empty-line-before": null, + "at-rule-empty-line-before": null, + "declaration-empty-line-before": null, + "selector-pseudo-element-colon-notation": "single", + "no-descending-specificity": null, + "function-whitespace-after": null, + "no-invalid-position-at-import-rule": null, + "selector-disallowed-list": [ + "/[.#]js-/", + { + "message": "js-* selectors can’t have visual styling. https://stackoverflow.design/product/guidelines/javascript/#javascript-classnames" + } + ] + } +} diff --git a/Gruntfile.js b/Gruntfile.js index 5ec79f0fee..727a037cfa 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -118,7 +118,7 @@ module.exports = function(grunt) { stacks_js: { files: ['lib/ts/**/*.ts'], // note: this doesn't watch any of the npm dependencies - tasks: ['concurrent:compile_stacks_js', 'copy:js2docs', 'copy:highlightJs', 'copy:editorJs', 'copy:editorCSS'] + tasks: ['concurrent:compile_stacks_js', 'copy:js2docs', 'copy:jQueryJs', 'copy:highlightJs', 'copy:docsearchJs', 'copy:listJs', 'copy:editorJs', 'copy:editorCSS'] }, }, // Run tasks in parallel @@ -136,7 +136,7 @@ module.exports = function(grunt) { compile: [ 'concurrent:compile_stacks_css', 'ts:docs_js', - ['concurrent:compile_stacks_js', 'copy:js2docs', 'copy:highlightJs', 'copy:editorJs', 'copy:editorCSS'] + ['concurrent:compile_stacks_js', 'copy:js2docs', 'copy:jQueryJs', 'copy:highlightJs', 'copy:docsearchJs', 'copy:listJs', 'copy:editorJs', 'copy:editorCSS'] ], // Stacks JS @@ -176,6 +176,15 @@ module.exports = function(grunt) { return dest + src.replace('app.bundle.js','library.stacks-editor.js'); } }, + jQueryJs: { + src: 'node_modules/jquery/dist/jquery.min.js', + dest: 'docs/assets/js/', + flatten: true, + expand: true, + rename: function(dest, src) { + return dest + src.replace('jquery.min.js','library.jquery.js'); + } + }, highlightJs: { src: 'node_modules/@highlightjs/cdn-assets/highlight.min.js', dest: 'docs/assets/js/', @@ -185,6 +194,24 @@ module.exports = function(grunt) { return dest + src.replace('highlight.min.js','library.highlight.js'); } }, + docsearchJs: { + src: 'node_modules/docsearch.js/dist/cdn/docsearch.min.js', + dest: 'docs/assets/js/', + flatten: true, + expand: true, + rename: function(dest, src) { + return dest + src.replace('docsearch.min.js','library.docsearch.js'); + } + }, + listJs: { + src: 'node_modules/list.js/dist/list.min.js', + dest: 'docs/assets/js/', + flatten: true, + expand: true, + rename: function(dest, src) { + return dest + src.replace('list.min.js','library.list.js'); + } + }, editorCSS: { src: 'node_modules/@stackoverflow/stacks-editor/dist/styles.css', dest: 'docs/assets/css/', diff --git a/README.md b/README.md index 8f1e16461b..539fa610cb 100755 --- a/README.md +++ b/README.md @@ -44,4 +44,4 @@ Have a bug or feature request? First search existing or closed issues to make su If you’d like to contribute to Stacks, please read through our [contribution guidelines](/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. ## License -Code and documentation copyright 2017-2021 Stack Exchange, Inc and released under the [MIT License](/LICENSE.MD). +Code and documentation copyright 2017-2022 Stack Exchange, Inc and released under the [MIT License](/LICENSE.MD). diff --git a/backstop.json b/backstop.json index 0023f266d3..c0d8336d4d 100644 --- a/backstop.json +++ b/backstop.json @@ -65,6 +65,13 @@ "url": "http://localhost:8080/product/guidelines/javascript" }, { + "selectors": [ + "document" + ], + "label": "Product Theming", + "url": "http://localhost:8080/product/guidelines/theming" + }, + { "selectors": [ "document" ], @@ -142,6 +149,13 @@ "url": "http://localhost:8080/product/base/display" }, { + "selectors": [ + "document" + ], + "label": "Product Flex", + "url": "http://localhost:8080/product/base/flex" + }, + { "selectors": [ "document" ], @@ -170,6 +184,13 @@ "url": "http://localhost:8080/product/base/lists" }, { + "selectors": [ + "document" + ], + "label": "Product Object Fit", + "url": "http://localhost:8080/product/base/object-fit" + }, + { "selectors": [ "document" ], @@ -247,6 +268,13 @@ "url": "http://localhost:8080/product/base/z-index" }, { + "selectors": [ + "document" + ], + "label": "Product Activity Indicator", + "url": "http://localhost:8080/product/components/activity-indicator" + }, + { "selectors": [ "document" ], @@ -303,6 +331,20 @@ "url": "http://localhost:8080/product/components/checkbox" }, { + "selectors": [ + "document" + ], + "label": "Product Code blocks", + "url": "http://localhost:8080/product/components/code-blocks" + }, + { + "selectors": [ + "document" + ], + "label": "Product Editor", + "url": "http://localhost:8080/product/components/editor" + }, + { "selectors": [ "document" ], @@ -387,6 +429,13 @@ "url": "http://localhost:8080/product/components/popovers" }, { + "selectors": [ + "document" + ], + "label": "Product Post Summary", + "url": "http://localhost:8080/product/components/post-summary" + }, + { "selectors": [ "document" ], @@ -457,6 +506,13 @@ "url": "http://localhost:8080/product/components/toggle-switch" }, { + "selectors": [ + "document" + ], + "label": "Product Uploader", + "url": "http://localhost:8080/product/components/uploader" + }, + { "selectors": [ "document" ], @@ -649,8 +705,29 @@ "selectors": [ "document" ], - "label": "Brand Logo", + "label": "Brand Naming Guidelines", + "url": "http://localhost:8080/brand/copywriting/naming" + }, + { + "selectors": [ + "document" + ], + "label": "Brand Logos", "url": "http://localhost:8080/brand/logo" + }, + { + "selectors": [ + "document" + ], + "label": "Brand Typography", + "url": "http://localhost:8080/brand/typography" + }, + { + "selectors": [ + "document" + ], + "label": "Brand Colors", + "url": "http://localhost:8080/brand/colors" } ], "paths": { diff --git a/dist/css/stacks-flexgrid-shim.min.css b/dist/css/stacks-flexgrid-shim.min.css new file mode 100644 index 0000000000..f62be54159 --- /dev/null +++ b/dist/css/stacks-flexgrid-shim.min.css @@ -0,0 +1 @@ +.grid{display:flex}.grid__fl0,.grid__fl0>.grid,.grid__fl0>.grid--cell{flex:0 auto}.grid__fl1,.grid__fl1>.grid,.grid__fl1>.grid--cell{flex:1 auto}.grid--cell1{flex-basis:8.33333333%}.grid--cell2{flex-basis:16.66666667%}.grid--cell3{flex-basis:25%}.grid--cell4{flex-basis:33.33333333%}.grid--cell5{flex-basis:41.66666667%}.grid--cell6{flex-basis:50%}.grid--cell7{flex-basis:58.33333333%}.grid--cell8{flex-basis:66.66666667%}.grid--cell9{flex-basis:75%}.grid--cell10{flex-basis:83.33333333%}.grid--cell11{flex-basis:91.66666667%}.grid--cell12{flex-basis:100%}.grid__allcells1>.grid,.grid__allcells1>.grid--cell{flex-basis:8.33333333%}.grid__allcells2>.grid,.grid__allcells2>.grid--cell{flex-basis:16.66666667%}.grid__allcells3>.grid,.grid__allcells3>.grid--cell{flex-basis:25%}.grid__allcells4>.grid,.grid__allcells4>.grid--cell{flex-basis:33.33333333%}.grid__allcells5>.grid,.grid__allcells5>.grid--cell{flex-basis:41.66666667%}.grid__allcells6>.grid,.grid__allcells6>.grid--cell{flex-basis:50%}.grid__allcells7>.grid,.grid__allcells7>.grid--cell{flex-basis:58.33333333%}.grid__allcells8>.grid,.grid__allcells8>.grid--cell{flex-basis:66.66666667%}.grid__allcells9>.grid,.grid__allcells9>.grid--cell{flex-basis:75%}.grid__allcells10>.grid,.grid__allcells10>.grid--cell{flex-basis:83.33333333%}.grid__allcells11>.grid,.grid__allcells11>.grid--cell{flex-basis:91.66666667%}.grid__allcells12>.grid,.grid__allcells12>.grid--cell{flex-basis:100%}.gs2{margin:-1px}.gs2>.grid,.gs2>.grid--cell{margin:1px}.gs2>.grid--cell1{margin:1px}.gs2.grid__allcells1>.grid,.gs2.grid__allcells1>.grid--cell,.gs2>.grid--cell1{flex-basis:calc(8.333333333333334% - 2px)}.gs2>.grid--cell2{margin:1px}.gs2.grid__allcells2>.grid,.gs2.grid__allcells2>.grid--cell,.gs2>.grid--cell2{flex-basis:calc(16.666666666666668% - 2px)}.gs2>.grid--cell3{margin:1px}.gs2.grid__allcells3>.grid,.gs2.grid__allcells3>.grid--cell,.gs2>.grid--cell3{flex-basis:calc(25% - 2px)}.gs2>.grid--cell4{margin:1px}.gs2.grid__allcells4>.grid,.gs2.grid__allcells4>.grid--cell,.gs2>.grid--cell4{flex-basis:calc(33.333333333333336% - 2px)}.gs2>.grid--cell5{margin:1px}.gs2.grid__allcells5>.grid,.gs2.grid__allcells5>.grid--cell,.gs2>.grid--cell5{flex-basis:calc(41.666666666666664% - 2px)}.gs2>.grid--cell6{margin:1px}.gs2.grid__allcells6>.grid,.gs2.grid__allcells6>.grid--cell,.gs2>.grid--cell6{flex-basis:calc(50% - 2px)}.gs2>.grid--cell7{margin:1px}.gs2.grid__allcells7>.grid,.gs2.grid__allcells7>.grid--cell,.gs2>.grid--cell7{flex-basis:calc(58.333333333333336% - 2px)}.gs2>.grid--cell8{margin:1px}.gs2.grid__allcells8>.grid,.gs2.grid__allcells8>.grid--cell,.gs2>.grid--cell8{flex-basis:calc(66.66666666666667% - 2px)}.gs2>.grid--cell9{margin:1px}.gs2.grid__allcells9>.grid,.gs2.grid__allcells9>.grid--cell,.gs2>.grid--cell9{flex-basis:calc(75% - 2px)}.gs2>.grid--cell10{margin:1px}.gs2.grid__allcells10>.grid,.gs2.grid__allcells10>.grid--cell,.gs2>.grid--cell10{flex-basis:calc(83.33333333333333% - 2px)}.gs2>.grid--cell11{margin:1px}.gs2.grid__allcells11>.grid,.gs2.grid__allcells11>.grid--cell,.gs2>.grid--cell11{flex-basis:calc(91.66666666666667% - 2px)}.gs2>.grid--cell12{margin:1px}.gs2.grid__allcells12>.grid,.gs2.grid__allcells12>.grid--cell,.gs2>.grid--cell12{flex-basis:calc(100% - 2px)}.gs4{margin:-2px}.gs4>.grid,.gs4>.grid--cell{margin:2px}.gs4>.grid--cell1{margin:2px}.gs4.grid__allcells1>.grid,.gs4.grid__allcells1>.grid--cell,.gs4>.grid--cell1{flex-basis:calc(8.333333333333334% - 4px)}.gs4>.grid--cell2{margin:2px}.gs4.grid__allcells2>.grid,.gs4.grid__allcells2>.grid--cell,.gs4>.grid--cell2{flex-basis:calc(16.666666666666668% - 4px)}.gs4>.grid--cell3{margin:2px}.gs4.grid__allcells3>.grid,.gs4.grid__allcells3>.grid--cell,.gs4>.grid--cell3{flex-basis:calc(25% - 4px)}.gs4>.grid--cell4{margin:2px}.gs4.grid__allcells4>.grid,.gs4.grid__allcells4>.grid--cell,.gs4>.grid--cell4{flex-basis:calc(33.333333333333336% - 4px)}.gs4>.grid--cell5{margin:2px}.gs4.grid__allcells5>.grid,.gs4.grid__allcells5>.grid--cell,.gs4>.grid--cell5{flex-basis:calc(41.666666666666664% - 4px)}.gs4>.grid--cell6{margin:2px}.gs4.grid__allcells6>.grid,.gs4.grid__allcells6>.grid--cell,.gs4>.grid--cell6{flex-basis:calc(50% - 4px)}.gs4>.grid--cell7{margin:2px}.gs4.grid__allcells7>.grid,.gs4.grid__allcells7>.grid--cell,.gs4>.grid--cell7{flex-basis:calc(58.333333333333336% - 4px)}.gs4>.grid--cell8{margin:2px}.gs4.grid__allcells8>.grid,.gs4.grid__allcells8>.grid--cell,.gs4>.grid--cell8{flex-basis:calc(66.66666666666667% - 4px)}.gs4>.grid--cell9{margin:2px}.gs4.grid__allcells9>.grid,.gs4.grid__allcells9>.grid--cell,.gs4>.grid--cell9{flex-basis:calc(75% - 4px)}.gs4>.grid--cell10{margin:2px}.gs4.grid__allcells10>.grid,.gs4.grid__allcells10>.grid--cell,.gs4>.grid--cell10{flex-basis:calc(83.33333333333333% - 4px)}.gs4>.grid--cell11{margin:2px}.gs4.grid__allcells11>.grid,.gs4.grid__allcells11>.grid--cell,.gs4>.grid--cell11{flex-basis:calc(91.66666666666667% - 4px)}.gs4>.grid--cell12{margin:2px}.gs4.grid__allcells12>.grid,.gs4.grid__allcells12>.grid--cell,.gs4>.grid--cell12{flex-basis:calc(100% - 4px)}.gs8{margin:-4px}.gs8>.grid,.gs8>.grid--cell{margin:4px}.gs8>.grid--cell1{margin:4px}.gs8.grid__allcells1>.grid,.gs8.grid__allcells1>.grid--cell,.gs8>.grid--cell1{flex-basis:calc(8.333333333333334% - 8px)}.gs8>.grid--cell2{margin:4px}.gs8.grid__allcells2>.grid,.gs8.grid__allcells2>.grid--cell,.gs8>.grid--cell2{flex-basis:calc(16.666666666666668% - 8px)}.gs8>.grid--cell3{margin:4px}.gs8.grid__allcells3>.grid,.gs8.grid__allcells3>.grid--cell,.gs8>.grid--cell3{flex-basis:calc(25% - 8px)}.gs8>.grid--cell4{margin:4px}.gs8.grid__allcells4>.grid,.gs8.grid__allcells4>.grid--cell,.gs8>.grid--cell4{flex-basis:calc(33.333333333333336% - 8px)}.gs8>.grid--cell5{margin:4px}.gs8.grid__allcells5>.grid,.gs8.grid__allcells5>.grid--cell,.gs8>.grid--cell5{flex-basis:calc(41.666666666666664% - 8px)}.gs8>.grid--cell6{margin:4px}.gs8.grid__allcells6>.grid,.gs8.grid__allcells6>.grid--cell,.gs8>.grid--cell6{flex-basis:calc(50% - 8px)}.gs8>.grid--cell7{margin:4px}.gs8.grid__allcells7>.grid,.gs8.grid__allcells7>.grid--cell,.gs8>.grid--cell7{flex-basis:calc(58.333333333333336% - 8px)}.gs8>.grid--cell8{margin:4px}.gs8.grid__allcells8>.grid,.gs8.grid__allcells8>.grid--cell,.gs8>.grid--cell8{flex-basis:calc(66.66666666666667% - 8px)}.gs8>.grid--cell9{margin:4px}.gs8.grid__allcells9>.grid,.gs8.grid__allcells9>.grid--cell,.gs8>.grid--cell9{flex-basis:calc(75% - 8px)}.gs8>.grid--cell10{margin:4px}.gs8.grid__allcells10>.grid,.gs8.grid__allcells10>.grid--cell,.gs8>.grid--cell10{flex-basis:calc(83.33333333333333% - 8px)}.gs8>.grid--cell11{margin:4px}.gs8.grid__allcells11>.grid,.gs8.grid__allcells11>.grid--cell,.gs8>.grid--cell11{flex-basis:calc(91.66666666666667% - 8px)}.gs8>.grid--cell12{margin:4px}.gs8.grid__allcells12>.grid,.gs8.grid__allcells12>.grid--cell,.gs8>.grid--cell12{flex-basis:calc(100% - 8px)}.gs12{margin:-6px}.gs12>.grid,.gs12>.grid--cell{margin:6px}.gs12>.grid--cell1{margin:6px}.gs12.grid__allcells1>.grid,.gs12.grid__allcells1>.grid--cell,.gs12>.grid--cell1{flex-basis:calc(8.333333333333334% - 12px)}.gs12>.grid--cell2{margin:6px}.gs12.grid__allcells2>.grid,.gs12.grid__allcells2>.grid--cell,.gs12>.grid--cell2{flex-basis:calc(16.666666666666668% - 12px)}.gs12>.grid--cell3{margin:6px}.gs12.grid__allcells3>.grid,.gs12.grid__allcells3>.grid--cell,.gs12>.grid--cell3{flex-basis:calc(25% - 12px)}.gs12>.grid--cell4{margin:6px}.gs12.grid__allcells4>.grid,.gs12.grid__allcells4>.grid--cell,.gs12>.grid--cell4{flex-basis:calc(33.333333333333336% - 12px)}.gs12>.grid--cell5{margin:6px}.gs12.grid__allcells5>.grid,.gs12.grid__allcells5>.grid--cell,.gs12>.grid--cell5{flex-basis:calc(41.666666666666664% - 12px)}.gs12>.grid--cell6{margin:6px}.gs12.grid__allcells6>.grid,.gs12.grid__allcells6>.grid--cell,.gs12>.grid--cell6{flex-basis:calc(50% - 12px)}.gs12>.grid--cell7{margin:6px}.gs12.grid__allcells7>.grid,.gs12.grid__allcells7>.grid--cell,.gs12>.grid--cell7{flex-basis:calc(58.333333333333336% - 12px)}.gs12>.grid--cell8{margin:6px}.gs12.grid__allcells8>.grid,.gs12.grid__allcells8>.grid--cell,.gs12>.grid--cell8{flex-basis:calc(66.66666666666667% - 12px)}.gs12>.grid--cell9{margin:6px}.gs12.grid__allcells9>.grid,.gs12.grid__allcells9>.grid--cell,.gs12>.grid--cell9{flex-basis:calc(75% - 12px)}.gs12>.grid--cell10{margin:6px}.gs12.grid__allcells10>.grid,.gs12.grid__allcells10>.grid--cell,.gs12>.grid--cell10{flex-basis:calc(83.33333333333333% - 12px)}.gs12>.grid--cell11{margin:6px}.gs12.grid__allcells11>.grid,.gs12.grid__allcells11>.grid--cell,.gs12>.grid--cell11{flex-basis:calc(91.66666666666667% - 12px)}.gs12>.grid--cell12{margin:6px}.gs12.grid__allcells12>.grid,.gs12.grid__allcells12>.grid--cell,.gs12>.grid--cell12{flex-basis:calc(100% - 12px)}.gs16{margin:-8px}.gs16>.grid,.gs16>.grid--cell{margin:8px}.gs16>.grid--cell1{margin:8px}.gs16.grid__allcells1>.grid,.gs16.grid__allcells1>.grid--cell,.gs16>.grid--cell1{flex-basis:calc(8.333333333333334% - 16px)}.gs16>.grid--cell2{margin:8px}.gs16.grid__allcells2>.grid,.gs16.grid__allcells2>.grid--cell,.gs16>.grid--cell2{flex-basis:calc(16.666666666666668% - 16px)}.gs16>.grid--cell3{margin:8px}.gs16.grid__allcells3>.grid,.gs16.grid__allcells3>.grid--cell,.gs16>.grid--cell3{flex-basis:calc(25% - 16px)}.gs16>.grid--cell4{margin:8px}.gs16.grid__allcells4>.grid,.gs16.grid__allcells4>.grid--cell,.gs16>.grid--cell4{flex-basis:calc(33.333333333333336% - 16px)}.gs16>.grid--cell5{margin:8px}.gs16.grid__allcells5>.grid,.gs16.grid__allcells5>.grid--cell,.gs16>.grid--cell5{flex-basis:calc(41.666666666666664% - 16px)}.gs16>.grid--cell6{margin:8px}.gs16.grid__allcells6>.grid,.gs16.grid__allcells6>.grid--cell,.gs16>.grid--cell6{flex-basis:calc(50% - 16px)}.gs16>.grid--cell7{margin:8px}.gs16.grid__allcells7>.grid,.gs16.grid__allcells7>.grid--cell,.gs16>.grid--cell7{flex-basis:calc(58.333333333333336% - 16px)}.gs16>.grid--cell8{margin:8px}.gs16.grid__allcells8>.grid,.gs16.grid__allcells8>.grid--cell,.gs16>.grid--cell8{flex-basis:calc(66.66666666666667% - 16px)}.gs16>.grid--cell9{margin:8px}.gs16.grid__allcells9>.grid,.gs16.grid__allcells9>.grid--cell,.gs16>.grid--cell9{flex-basis:calc(75% - 16px)}.gs16>.grid--cell10{margin:8px}.gs16.grid__allcells10>.grid,.gs16.grid__allcells10>.grid--cell,.gs16>.grid--cell10{flex-basis:calc(83.33333333333333% - 16px)}.gs16>.grid--cell11{margin:8px}.gs16.grid__allcells11>.grid,.gs16.grid__allcells11>.grid--cell,.gs16>.grid--cell11{flex-basis:calc(91.66666666666667% - 16px)}.gs16>.grid--cell12{margin:8px}.gs16.grid__allcells12>.grid,.gs16.grid__allcells12>.grid--cell,.gs16>.grid--cell12{flex-basis:calc(100% - 16px)}.gs24{margin:-12px}.gs24>.grid,.gs24>.grid--cell{margin:12px}.gs24>.grid--cell1{margin:12px}.gs24.grid__allcells1>.grid,.gs24.grid__allcells1>.grid--cell,.gs24>.grid--cell1{flex-basis:calc(8.333333333333334% - 24px)}.gs24>.grid--cell2{margin:12px}.gs24.grid__allcells2>.grid,.gs24.grid__allcells2>.grid--cell,.gs24>.grid--cell2{flex-basis:calc(16.666666666666668% - 24px)}.gs24>.grid--cell3{margin:12px}.gs24.grid__allcells3>.grid,.gs24.grid__allcells3>.grid--cell,.gs24>.grid--cell3{flex-basis:calc(25% - 24px)}.gs24>.grid--cell4{margin:12px}.gs24.grid__allcells4>.grid,.gs24.grid__allcells4>.grid--cell,.gs24>.grid--cell4{flex-basis:calc(33.333333333333336% - 24px)}.gs24>.grid--cell5{margin:12px}.gs24.grid__allcells5>.grid,.gs24.grid__allcells5>.grid--cell,.gs24>.grid--cell5{flex-basis:calc(41.666666666666664% - 24px)}.gs24>.grid--cell6{margin:12px}.gs24.grid__allcells6>.grid,.gs24.grid__allcells6>.grid--cell,.gs24>.grid--cell6{flex-basis:calc(50% - 24px)}.gs24>.grid--cell7{margin:12px}.gs24.grid__allcells7>.grid,.gs24.grid__allcells7>.grid--cell,.gs24>.grid--cell7{flex-basis:calc(58.333333333333336% - 24px)}.gs24>.grid--cell8{margin:12px}.gs24.grid__allcells8>.grid,.gs24.grid__allcells8>.grid--cell,.gs24>.grid--cell8{flex-basis:calc(66.66666666666667% - 24px)}.gs24>.grid--cell9{margin:12px}.gs24.grid__allcells9>.grid,.gs24.grid__allcells9>.grid--cell,.gs24>.grid--cell9{flex-basis:calc(75% - 24px)}.gs24>.grid--cell10{margin:12px}.gs24.grid__allcells10>.grid,.gs24.grid__allcells10>.grid--cell,.gs24>.grid--cell10{flex-basis:calc(83.33333333333333% - 24px)}.gs24>.grid--cell11{margin:12px}.gs24.grid__allcells11>.grid,.gs24.grid__allcells11>.grid--cell,.gs24>.grid--cell11{flex-basis:calc(91.66666666666667% - 24px)}.gs24>.grid--cell12{margin:12px}.gs24.grid__allcells12>.grid,.gs24.grid__allcells12>.grid--cell,.gs24>.grid--cell12{flex-basis:calc(100% - 24px)}.gs32{margin:-16px}.gs32>.grid,.gs32>.grid--cell{margin:16px}.gs32>.grid--cell1{margin:16px}.gs32.grid__allcells1>.grid,.gs32.grid__allcells1>.grid--cell,.gs32>.grid--cell1{flex-basis:calc(8.333333333333334% - 32px)}.gs32>.grid--cell2{margin:16px}.gs32.grid__allcells2>.grid,.gs32.grid__allcells2>.grid--cell,.gs32>.grid--cell2{flex-basis:calc(16.666666666666668% - 32px)}.gs32>.grid--cell3{margin:16px}.gs32.grid__allcells3>.grid,.gs32.grid__allcells3>.grid--cell,.gs32>.grid--cell3{flex-basis:calc(25% - 32px)}.gs32>.grid--cell4{margin:16px}.gs32.grid__allcells4>.grid,.gs32.grid__allcells4>.grid--cell,.gs32>.grid--cell4{flex-basis:calc(33.333333333333336% - 32px)}.gs32>.grid--cell5{margin:16px}.gs32.grid__allcells5>.grid,.gs32.grid__allcells5>.grid--cell,.gs32>.grid--cell5{flex-basis:calc(41.666666666666664% - 32px)}.gs32>.grid--cell6{margin:16px}.gs32.grid__allcells6>.grid,.gs32.grid__allcells6>.grid--cell,.gs32>.grid--cell6{flex-basis:calc(50% - 32px)}.gs32>.grid--cell7{margin:16px}.gs32.grid__allcells7>.grid,.gs32.grid__allcells7>.grid--cell,.gs32>.grid--cell7{flex-basis:calc(58.333333333333336% - 32px)}.gs32>.grid--cell8{margin:16px}.gs32.grid__allcells8>.grid,.gs32.grid__allcells8>.grid--cell,.gs32>.grid--cell8{flex-basis:calc(66.66666666666667% - 32px)}.gs32>.grid--cell9{margin:16px}.gs32.grid__allcells9>.grid,.gs32.grid__allcells9>.grid--cell,.gs32>.grid--cell9{flex-basis:calc(75% - 32px)}.gs32>.grid--cell10{margin:16px}.gs32.grid__allcells10>.grid,.gs32.grid__allcells10>.grid--cell,.gs32>.grid--cell10{flex-basis:calc(83.33333333333333% - 32px)}.gs32>.grid--cell11{margin:16px}.gs32.grid__allcells11>.grid,.gs32.grid__allcells11>.grid--cell,.gs32>.grid--cell11{flex-basis:calc(91.66666666666667% - 32px)}.gs32>.grid--cell12{margin:16px}.gs32.grid__allcells12>.grid,.gs32.grid__allcells12>.grid--cell,.gs32>.grid--cell12{flex-basis:calc(100% - 32px)}.gs48{margin:-24px}.gs48>.grid,.gs48>.grid--cell{margin:24px}.gs48>.grid--cell1{margin:24px}.gs48.grid__allcells1>.grid,.gs48.grid__allcells1>.grid--cell,.gs48>.grid--cell1{flex-basis:calc(8.333333333333334% - 48px)}.gs48>.grid--cell2{margin:24px}.gs48.grid__allcells2>.grid,.gs48.grid__allcells2>.grid--cell,.gs48>.grid--cell2{flex-basis:calc(16.666666666666668% - 48px)}.gs48>.grid--cell3{margin:24px}.gs48.grid__allcells3>.grid,.gs48.grid__allcells3>.grid--cell,.gs48>.grid--cell3{flex-basis:calc(25% - 48px)}.gs48>.grid--cell4{margin:24px}.gs48.grid__allcells4>.grid,.gs48.grid__allcells4>.grid--cell,.gs48>.grid--cell4{flex-basis:calc(33.333333333333336% - 48px)}.gs48>.grid--cell5{margin:24px}.gs48.grid__allcells5>.grid,.gs48.grid__allcells5>.grid--cell,.gs48>.grid--cell5{flex-basis:calc(41.666666666666664% - 48px)}.gs48>.grid--cell6{margin:24px}.gs48.grid__allcells6>.grid,.gs48.grid__allcells6>.grid--cell,.gs48>.grid--cell6{flex-basis:calc(50% - 48px)}.gs48>.grid--cell7{margin:24px}.gs48.grid__allcells7>.grid,.gs48.grid__allcells7>.grid--cell,.gs48>.grid--cell7{flex-basis:calc(58.333333333333336% - 48px)}.gs48>.grid--cell8{margin:24px}.gs48.grid__allcells8>.grid,.gs48.grid__allcells8>.grid--cell,.gs48>.grid--cell8{flex-basis:calc(66.66666666666667% - 48px)}.gs48>.grid--cell9{margin:24px}.gs48.grid__allcells9>.grid,.gs48.grid__allcells9>.grid--cell,.gs48>.grid--cell9{flex-basis:calc(75% - 48px)}.gs48>.grid--cell10{margin:24px}.gs48.grid__allcells10>.grid,.gs48.grid__allcells10>.grid--cell,.gs48>.grid--cell10{flex-basis:calc(83.33333333333333% - 48px)}.gs48>.grid--cell11{margin:24px}.gs48.grid__allcells11>.grid,.gs48.grid__allcells11>.grid--cell,.gs48>.grid--cell11{flex-basis:calc(91.66666666666667% - 48px)}.gs48>.grid--cell12{margin:24px}.gs48.grid__allcells12>.grid,.gs48.grid__allcells12>.grid--cell,.gs48>.grid--cell12{flex-basis:calc(100% - 48px)}.gs64{margin:-32px}.gs64>.grid,.gs64>.grid--cell{margin:32px}.gs64>.grid--cell1{margin:32px}.gs64.grid__allcells1>.grid,.gs64.grid__allcells1>.grid--cell,.gs64>.grid--cell1{flex-basis:calc(8.333333333333334% - 64px)}.gs64>.grid--cell2{margin:32px}.gs64.grid__allcells2>.grid,.gs64.grid__allcells2>.grid--cell,.gs64>.grid--cell2{flex-basis:calc(16.666666666666668% - 64px)}.gs64>.grid--cell3{margin:32px}.gs64.grid__allcells3>.grid,.gs64.grid__allcells3>.grid--cell,.gs64>.grid--cell3{flex-basis:calc(25% - 64px)}.gs64>.grid--cell4{margin:32px}.gs64.grid__allcells4>.grid,.gs64.grid__allcells4>.grid--cell,.gs64>.grid--cell4{flex-basis:calc(33.333333333333336% - 64px)}.gs64>.grid--cell5{margin:32px}.gs64.grid__allcells5>.grid,.gs64.grid__allcells5>.grid--cell,.gs64>.grid--cell5{flex-basis:calc(41.666666666666664% - 64px)}.gs64>.grid--cell6{margin:32px}.gs64.grid__allcells6>.grid,.gs64.grid__allcells6>.grid--cell,.gs64>.grid--cell6{flex-basis:calc(50% - 64px)}.gs64>.grid--cell7{margin:32px}.gs64.grid__allcells7>.grid,.gs64.grid__allcells7>.grid--cell,.gs64>.grid--cell7{flex-basis:calc(58.333333333333336% - 64px)}.gs64>.grid--cell8{margin:32px}.gs64.grid__allcells8>.grid,.gs64.grid__allcells8>.grid--cell,.gs64>.grid--cell8{flex-basis:calc(66.66666666666667% - 64px)}.gs64>.grid--cell9{margin:32px}.gs64.grid__allcells9>.grid,.gs64.grid__allcells9>.grid--cell,.gs64>.grid--cell9{flex-basis:calc(75% - 64px)}.gs64>.grid--cell10{margin:32px}.gs64.grid__allcells10>.grid,.gs64.grid__allcells10>.grid--cell,.gs64>.grid--cell10{flex-basis:calc(83.33333333333333% - 64px)}.gs64>.grid--cell11{margin:32px}.gs64.grid__allcells11>.grid,.gs64.grid__allcells11>.grid--cell,.gs64>.grid--cell11{flex-basis:calc(91.66666666666667% - 64px)}.gs64>.grid--cell12{margin:32px}.gs64.grid__allcells12>.grid,.gs64.grid__allcells12>.grid--cell,.gs64>.grid--cell12{flex-basis:calc(100% - 64px)}.gsx,.gsx>.grid,.gsx>[class*=grid--cell]{margin-top:0;margin-bottom:0}.gsy,.gsy>.grid,.gsy>[class*=grid--cell]{margin-right:0;margin-left:0}.s-btn.grid{display:flex} \ No newline at end of file diff --git a/dist/js/stacks.d.ts b/dist/js/stacks.d.ts deleted file mode 100644 index a6d892eafd..0000000000 --- a/dist/js/stacks.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -declare namespace Stacks { - const application: Stimulus.Application; - var _initializing: boolean; - class StacksController extends Stimulus.Controller { - protected getElementData(element: Element, key: string): string | null; - protected setElementData(element: Element, key: string, value: string): void; - protected removeElementData(element: Element, key: string): void; - protected triggerEvent(eventName: string, detail?: T, optionalElement?: Element): CustomEvent; - } - interface ControllerDefinition { - [name: string]: any; - targets?: string[]; - } - function createController(controllerDefinition: ControllerDefinition): typeof StacksController; - function addController(name: string, controller: ControllerDefinition): void; -} diff --git a/dist/js/stacks.js b/dist/js/stacks.js deleted file mode 100644 index dab7bfa16a..0000000000 --- a/dist/js/stacks.js +++ /dev/null @@ -1,4879 +0,0 @@ -/* -Stimulus 1.1.1 -Copyright © 2019 Basecamp, LLC - */ -(function(global, factory) { - typeof exports === "object" && typeof module !== "undefined" ? factory(exports) : typeof define === "function" && define.amd ? define([ "exports" ], factory) : factory(global.Stimulus = {}); -})(this, function(exports) { - "use strict"; - var EventListener = function() { - function EventListener(eventTarget, eventName) { - this.eventTarget = eventTarget; - this.eventName = eventName; - this.unorderedBindings = new Set(); - } - EventListener.prototype.connect = function() { - this.eventTarget.addEventListener(this.eventName, this, false); - }; - EventListener.prototype.disconnect = function() { - this.eventTarget.removeEventListener(this.eventName, this, false); - }; - EventListener.prototype.bindingConnected = function(binding) { - this.unorderedBindings.add(binding); - }; - EventListener.prototype.bindingDisconnected = function(binding) { - this.unorderedBindings.delete(binding); - }; - EventListener.prototype.handleEvent = function(event) { - var extendedEvent = extendEvent(event); - for (var _i = 0, _a = this.bindings; _i < _a.length; _i++) { - var binding = _a[_i]; - if (extendedEvent.immediatePropagationStopped) { - break; - } else { - binding.handleEvent(extendedEvent); - } - } - }; - Object.defineProperty(EventListener.prototype, "bindings", { - get: function() { - return Array.from(this.unorderedBindings).sort(function(left, right) { - var leftIndex = left.index, rightIndex = right.index; - return leftIndex < rightIndex ? -1 : leftIndex > rightIndex ? 1 : 0; - }); - }, - enumerable: true, - configurable: true - }); - return EventListener; - }(); - function extendEvent(event) { - if ("immediatePropagationStopped" in event) { - return event; - } else { - var stopImmediatePropagation_1 = event.stopImmediatePropagation; - return Object.assign(event, { - immediatePropagationStopped: false, - stopImmediatePropagation: function() { - this.immediatePropagationStopped = true; - stopImmediatePropagation_1.call(this); - } - }); - } - } - var Dispatcher = function() { - function Dispatcher(application) { - this.application = application; - this.eventListenerMaps = new Map(); - this.started = false; - } - Dispatcher.prototype.start = function() { - if (!this.started) { - this.started = true; - this.eventListeners.forEach(function(eventListener) { - return eventListener.connect(); - }); - } - }; - Dispatcher.prototype.stop = function() { - if (this.started) { - this.started = false; - this.eventListeners.forEach(function(eventListener) { - return eventListener.disconnect(); - }); - } - }; - Object.defineProperty(Dispatcher.prototype, "eventListeners", { - get: function() { - return Array.from(this.eventListenerMaps.values()).reduce(function(listeners, map) { - return listeners.concat(Array.from(map.values())); - }, []); - }, - enumerable: true, - configurable: true - }); - Dispatcher.prototype.bindingConnected = function(binding) { - this.fetchEventListenerForBinding(binding).bindingConnected(binding); - }; - Dispatcher.prototype.bindingDisconnected = function(binding) { - this.fetchEventListenerForBinding(binding).bindingDisconnected(binding); - }; - Dispatcher.prototype.handleError = function(error, message, detail) { - if (detail === void 0) { - detail = {}; - } - this.application.handleError(error, "Error " + message, detail); - }; - Dispatcher.prototype.fetchEventListenerForBinding = function(binding) { - var eventTarget = binding.eventTarget, eventName = binding.eventName; - return this.fetchEventListener(eventTarget, eventName); - }; - Dispatcher.prototype.fetchEventListener = function(eventTarget, eventName) { - var eventListenerMap = this.fetchEventListenerMapForEventTarget(eventTarget); - var eventListener = eventListenerMap.get(eventName); - if (!eventListener) { - eventListener = this.createEventListener(eventTarget, eventName); - eventListenerMap.set(eventName, eventListener); - } - return eventListener; - }; - Dispatcher.prototype.createEventListener = function(eventTarget, eventName) { - var eventListener = new EventListener(eventTarget, eventName); - if (this.started) { - eventListener.connect(); - } - return eventListener; - }; - Dispatcher.prototype.fetchEventListenerMapForEventTarget = function(eventTarget) { - var eventListenerMap = this.eventListenerMaps.get(eventTarget); - if (!eventListenerMap) { - eventListenerMap = new Map(); - this.eventListenerMaps.set(eventTarget, eventListenerMap); - } - return eventListenerMap; - }; - return Dispatcher; - }(); - var descriptorPattern = /^((.+?)(@(window|document))?->)?(.+?)(#(.+))?$/; - function parseDescriptorString(descriptorString) { - var source = descriptorString.trim(); - var matches = source.match(descriptorPattern) || []; - return { - eventTarget: parseEventTarget(matches[4]), - eventName: matches[2], - identifier: matches[5], - methodName: matches[7] - }; - } - function parseEventTarget(eventTargetName) { - if (eventTargetName == "window") { - return window; - } else if (eventTargetName == "document") { - return document; - } - } - function stringifyEventTarget(eventTarget) { - if (eventTarget == window) { - return "window"; - } else if (eventTarget == document) { - return "document"; - } - } - var Action = function() { - function Action(element, index, descriptor) { - this.element = element; - this.index = index; - this.eventTarget = descriptor.eventTarget || element; - this.eventName = descriptor.eventName || getDefaultEventNameForElement(element) || error("missing event name"); - this.identifier = descriptor.identifier || error("missing identifier"); - this.methodName = descriptor.methodName || error("missing method name"); - } - Action.forToken = function(token) { - return new this(token.element, token.index, parseDescriptorString(token.content)); - }; - Action.prototype.toString = function() { - var eventNameSuffix = this.eventTargetName ? "@" + this.eventTargetName : ""; - return "" + this.eventName + eventNameSuffix + "->" + this.identifier + "#" + this.methodName; - }; - Object.defineProperty(Action.prototype, "eventTargetName", { - get: function() { - return stringifyEventTarget(this.eventTarget); - }, - enumerable: true, - configurable: true - }); - return Action; - }(); - var defaultEventNames = { - a: function(e) { - return "click"; - }, - button: function(e) { - return "click"; - }, - form: function(e) { - return "submit"; - }, - input: function(e) { - return e.getAttribute("type") == "submit" ? "click" : "change"; - }, - select: function(e) { - return "change"; - }, - textarea: function(e) { - return "change"; - } - }; - function getDefaultEventNameForElement(element) { - var tagName = element.tagName.toLowerCase(); - if (tagName in defaultEventNames) { - return defaultEventNames[tagName](element); - } - } - function error(message) { - throw new Error(message); - } - var Binding = function() { - function Binding(context, action) { - this.context = context; - this.action = action; - } - Object.defineProperty(Binding.prototype, "index", { - get: function() { - return this.action.index; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Binding.prototype, "eventTarget", { - get: function() { - return this.action.eventTarget; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Binding.prototype, "identifier", { - get: function() { - return this.context.identifier; - }, - enumerable: true, - configurable: true - }); - Binding.prototype.handleEvent = function(event) { - if (this.willBeInvokedByEvent(event)) { - this.invokeWithEvent(event); - } - }; - Object.defineProperty(Binding.prototype, "eventName", { - get: function() { - return this.action.eventName; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Binding.prototype, "method", { - get: function() { - var method = this.controller[this.methodName]; - if (typeof method == "function") { - return method; - } - throw new Error('Action "' + this.action + '" references undefined method "' + this.methodName + '"'); - }, - enumerable: true, - configurable: true - }); - Binding.prototype.invokeWithEvent = function(event) { - try { - this.method.call(this.controller, event); - } catch (error) { - var _a = this, identifier = _a.identifier, controller = _a.controller, element = _a.element, index = _a.index; - var detail = { - identifier: identifier, - controller: controller, - element: element, - index: index, - event: event - }; - this.context.handleError(error, 'invoking action "' + this.action + '"', detail); - } - }; - Binding.prototype.willBeInvokedByEvent = function(event) { - var eventTarget = event.target; - if (this.element === eventTarget) { - return true; - } else if (eventTarget instanceof Element && this.element.contains(eventTarget)) { - return this.scope.containsElement(eventTarget); - } else { - return true; - } - }; - Object.defineProperty(Binding.prototype, "controller", { - get: function() { - return this.context.controller; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Binding.prototype, "methodName", { - get: function() { - return this.action.methodName; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Binding.prototype, "element", { - get: function() { - return this.scope.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Binding.prototype, "scope", { - get: function() { - return this.context.scope; - }, - enumerable: true, - configurable: true - }); - return Binding; - }(); - var ElementObserver = function() { - function ElementObserver(element, delegate) { - var _this = this; - this.element = element; - this.started = false; - this.delegate = delegate; - this.elements = new Set(); - this.mutationObserver = new MutationObserver(function(mutations) { - return _this.processMutations(mutations); - }); - } - ElementObserver.prototype.start = function() { - if (!this.started) { - this.started = true; - this.mutationObserver.observe(this.element, { - attributes: true, - childList: true, - subtree: true - }); - this.refresh(); - } - }; - ElementObserver.prototype.stop = function() { - if (this.started) { - this.mutationObserver.takeRecords(); - this.mutationObserver.disconnect(); - this.started = false; - } - }; - ElementObserver.prototype.refresh = function() { - if (this.started) { - var matches = new Set(this.matchElementsInTree()); - for (var _i = 0, _a = Array.from(this.elements); _i < _a.length; _i++) { - var element = _a[_i]; - if (!matches.has(element)) { - this.removeElement(element); - } - } - for (var _b = 0, _c = Array.from(matches); _b < _c.length; _b++) { - var element = _c[_b]; - this.addElement(element); - } - } - }; - ElementObserver.prototype.processMutations = function(mutations) { - if (this.started) { - for (var _i = 0, mutations_1 = mutations; _i < mutations_1.length; _i++) { - var mutation = mutations_1[_i]; - this.processMutation(mutation); - } - } - }; - ElementObserver.prototype.processMutation = function(mutation) { - if (mutation.type == "attributes") { - this.processAttributeChange(mutation.target, mutation.attributeName); - } else if (mutation.type == "childList") { - this.processRemovedNodes(mutation.removedNodes); - this.processAddedNodes(mutation.addedNodes); - } - }; - ElementObserver.prototype.processAttributeChange = function(node, attributeName) { - var element = node; - if (this.elements.has(element)) { - if (this.delegate.elementAttributeChanged && this.matchElement(element)) { - this.delegate.elementAttributeChanged(element, attributeName); - } else { - this.removeElement(element); - } - } else if (this.matchElement(element)) { - this.addElement(element); - } - }; - ElementObserver.prototype.processRemovedNodes = function(nodes) { - for (var _i = 0, _a = Array.from(nodes); _i < _a.length; _i++) { - var node = _a[_i]; - var element = this.elementFromNode(node); - if (element) { - this.processTree(element, this.removeElement); - } - } - }; - ElementObserver.prototype.processAddedNodes = function(nodes) { - for (var _i = 0, _a = Array.from(nodes); _i < _a.length; _i++) { - var node = _a[_i]; - var element = this.elementFromNode(node); - if (element && this.elementIsActive(element)) { - this.processTree(element, this.addElement); - } - } - }; - ElementObserver.prototype.matchElement = function(element) { - return this.delegate.matchElement(element); - }; - ElementObserver.prototype.matchElementsInTree = function(tree) { - if (tree === void 0) { - tree = this.element; - } - return this.delegate.matchElementsInTree(tree); - }; - ElementObserver.prototype.processTree = function(tree, processor) { - for (var _i = 0, _a = this.matchElementsInTree(tree); _i < _a.length; _i++) { - var element = _a[_i]; - processor.call(this, element); - } - }; - ElementObserver.prototype.elementFromNode = function(node) { - if (node.nodeType == Node.ELEMENT_NODE) { - return node; - } - }; - ElementObserver.prototype.elementIsActive = function(element) { - if (element.isConnected != this.element.isConnected) { - return false; - } else { - return this.element.contains(element); - } - }; - ElementObserver.prototype.addElement = function(element) { - if (!this.elements.has(element)) { - if (this.elementIsActive(element)) { - this.elements.add(element); - if (this.delegate.elementMatched) { - this.delegate.elementMatched(element); - } - } - } - }; - ElementObserver.prototype.removeElement = function(element) { - if (this.elements.has(element)) { - this.elements.delete(element); - if (this.delegate.elementUnmatched) { - this.delegate.elementUnmatched(element); - } - } - }; - return ElementObserver; - }(); - var AttributeObserver = function() { - function AttributeObserver(element, attributeName, delegate) { - this.attributeName = attributeName; - this.delegate = delegate; - this.elementObserver = new ElementObserver(element, this); - } - Object.defineProperty(AttributeObserver.prototype, "element", { - get: function() { - return this.elementObserver.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(AttributeObserver.prototype, "selector", { - get: function() { - return "[" + this.attributeName + "]"; - }, - enumerable: true, - configurable: true - }); - AttributeObserver.prototype.start = function() { - this.elementObserver.start(); - }; - AttributeObserver.prototype.stop = function() { - this.elementObserver.stop(); - }; - AttributeObserver.prototype.refresh = function() { - this.elementObserver.refresh(); - }; - Object.defineProperty(AttributeObserver.prototype, "started", { - get: function() { - return this.elementObserver.started; - }, - enumerable: true, - configurable: true - }); - AttributeObserver.prototype.matchElement = function(element) { - return element.hasAttribute(this.attributeName); - }; - AttributeObserver.prototype.matchElementsInTree = function(tree) { - var match = this.matchElement(tree) ? [ tree ] : []; - var matches = Array.from(tree.querySelectorAll(this.selector)); - return match.concat(matches); - }; - AttributeObserver.prototype.elementMatched = function(element) { - if (this.delegate.elementMatchedAttribute) { - this.delegate.elementMatchedAttribute(element, this.attributeName); - } - }; - AttributeObserver.prototype.elementUnmatched = function(element) { - if (this.delegate.elementUnmatchedAttribute) { - this.delegate.elementUnmatchedAttribute(element, this.attributeName); - } - }; - AttributeObserver.prototype.elementAttributeChanged = function(element, attributeName) { - if (this.delegate.elementAttributeValueChanged && this.attributeName == attributeName) { - this.delegate.elementAttributeValueChanged(element, attributeName); - } - }; - return AttributeObserver; - }(); - function add(map, key, value) { - fetch(map, key).add(value); - } - function del(map, key, value) { - fetch(map, key).delete(value); - prune(map, key); - } - function fetch(map, key) { - var values = map.get(key); - if (!values) { - values = new Set(); - map.set(key, values); - } - return values; - } - function prune(map, key) { - var values = map.get(key); - if (values != null && values.size == 0) { - map.delete(key); - } - } - var Multimap = function() { - function Multimap() { - this.valuesByKey = new Map(); - } - Object.defineProperty(Multimap.prototype, "values", { - get: function() { - var sets = Array.from(this.valuesByKey.values()); - return sets.reduce(function(values, set) { - return values.concat(Array.from(set)); - }, []); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Multimap.prototype, "size", { - get: function() { - var sets = Array.from(this.valuesByKey.values()); - return sets.reduce(function(size, set) { - return size + set.size; - }, 0); - }, - enumerable: true, - configurable: true - }); - Multimap.prototype.add = function(key, value) { - add(this.valuesByKey, key, value); - }; - Multimap.prototype.delete = function(key, value) { - del(this.valuesByKey, key, value); - }; - Multimap.prototype.has = function(key, value) { - var values = this.valuesByKey.get(key); - return values != null && values.has(value); - }; - Multimap.prototype.hasKey = function(key) { - return this.valuesByKey.has(key); - }; - Multimap.prototype.hasValue = function(value) { - var sets = Array.from(this.valuesByKey.values()); - return sets.some(function(set) { - return set.has(value); - }); - }; - Multimap.prototype.getValuesForKey = function(key) { - var values = this.valuesByKey.get(key); - return values ? Array.from(values) : []; - }; - Multimap.prototype.getKeysForValue = function(value) { - return Array.from(this.valuesByKey).filter(function(_a) { - var key = _a[0], values = _a[1]; - return values.has(value); - }).map(function(_a) { - var key = _a[0], values = _a[1]; - return key; - }); - }; - return Multimap; - }(); - var __extends = undefined && undefined.__extends || function() { - var extendStatics = Object.setPrototypeOf || { - __proto__: [] - } instanceof Array && function(d, b) { - d.__proto__ = b; - } || function(d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function(d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; - }(); - var IndexedMultimap = function(_super) { - __extends(IndexedMultimap, _super); - function IndexedMultimap() { - var _this = _super.call(this) || this; - _this.keysByValue = new Map(); - return _this; - } - Object.defineProperty(IndexedMultimap.prototype, "values", { - get: function() { - return Array.from(this.keysByValue.keys()); - }, - enumerable: true, - configurable: true - }); - IndexedMultimap.prototype.add = function(key, value) { - _super.prototype.add.call(this, key, value); - add(this.keysByValue, value, key); - }; - IndexedMultimap.prototype.delete = function(key, value) { - _super.prototype.delete.call(this, key, value); - del(this.keysByValue, value, key); - }; - IndexedMultimap.prototype.hasValue = function(value) { - return this.keysByValue.has(value); - }; - IndexedMultimap.prototype.getKeysForValue = function(value) { - var set = this.keysByValue.get(value); - return set ? Array.from(set) : []; - }; - return IndexedMultimap; - }(Multimap); - var TokenListObserver = function() { - function TokenListObserver(element, attributeName, delegate) { - this.attributeObserver = new AttributeObserver(element, attributeName, this); - this.delegate = delegate; - this.tokensByElement = new Multimap(); - } - Object.defineProperty(TokenListObserver.prototype, "started", { - get: function() { - return this.attributeObserver.started; - }, - enumerable: true, - configurable: true - }); - TokenListObserver.prototype.start = function() { - this.attributeObserver.start(); - }; - TokenListObserver.prototype.stop = function() { - this.attributeObserver.stop(); - }; - TokenListObserver.prototype.refresh = function() { - this.attributeObserver.refresh(); - }; - Object.defineProperty(TokenListObserver.prototype, "element", { - get: function() { - return this.attributeObserver.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(TokenListObserver.prototype, "attributeName", { - get: function() { - return this.attributeObserver.attributeName; - }, - enumerable: true, - configurable: true - }); - TokenListObserver.prototype.elementMatchedAttribute = function(element) { - this.tokensMatched(this.readTokensForElement(element)); - }; - TokenListObserver.prototype.elementAttributeValueChanged = function(element) { - var _a = this.refreshTokensForElement(element), unmatchedTokens = _a[0], matchedTokens = _a[1]; - this.tokensUnmatched(unmatchedTokens); - this.tokensMatched(matchedTokens); - }; - TokenListObserver.prototype.elementUnmatchedAttribute = function(element) { - this.tokensUnmatched(this.tokensByElement.getValuesForKey(element)); - }; - TokenListObserver.prototype.tokensMatched = function(tokens) { - var _this = this; - tokens.forEach(function(token) { - return _this.tokenMatched(token); - }); - }; - TokenListObserver.prototype.tokensUnmatched = function(tokens) { - var _this = this; - tokens.forEach(function(token) { - return _this.tokenUnmatched(token); - }); - }; - TokenListObserver.prototype.tokenMatched = function(token) { - this.delegate.tokenMatched(token); - this.tokensByElement.add(token.element, token); - }; - TokenListObserver.prototype.tokenUnmatched = function(token) { - this.delegate.tokenUnmatched(token); - this.tokensByElement.delete(token.element, token); - }; - TokenListObserver.prototype.refreshTokensForElement = function(element) { - var previousTokens = this.tokensByElement.getValuesForKey(element); - var currentTokens = this.readTokensForElement(element); - var firstDifferingIndex = zip(previousTokens, currentTokens).findIndex(function(_a) { - var previousToken = _a[0], currentToken = _a[1]; - return !tokensAreEqual(previousToken, currentToken); - }); - if (firstDifferingIndex == -1) { - return [ [], [] ]; - } else { - return [ previousTokens.slice(firstDifferingIndex), currentTokens.slice(firstDifferingIndex) ]; - } - }; - TokenListObserver.prototype.readTokensForElement = function(element) { - var attributeName = this.attributeName; - var tokenString = element.getAttribute(attributeName) || ""; - return parseTokenString(tokenString, element, attributeName); - }; - return TokenListObserver; - }(); - function parseTokenString(tokenString, element, attributeName) { - return tokenString.trim().split(/\s+/).filter(function(content) { - return content.length; - }).map(function(content, index) { - return { - element: element, - attributeName: attributeName, - content: content, - index: index - }; - }); - } - function zip(left, right) { - var length = Math.max(left.length, right.length); - return Array.from({ - length: length - }, function(_, index) { - return [ left[index], right[index] ]; - }); - } - function tokensAreEqual(left, right) { - return left && right && left.index == right.index && left.content == right.content; - } - var ValueListObserver = function() { - function ValueListObserver(element, attributeName, delegate) { - this.tokenListObserver = new TokenListObserver(element, attributeName, this); - this.delegate = delegate; - this.parseResultsByToken = new WeakMap(); - this.valuesByTokenByElement = new WeakMap(); - } - Object.defineProperty(ValueListObserver.prototype, "started", { - get: function() { - return this.tokenListObserver.started; - }, - enumerable: true, - configurable: true - }); - ValueListObserver.prototype.start = function() { - this.tokenListObserver.start(); - }; - ValueListObserver.prototype.stop = function() { - this.tokenListObserver.stop(); - }; - ValueListObserver.prototype.refresh = function() { - this.tokenListObserver.refresh(); - }; - Object.defineProperty(ValueListObserver.prototype, "element", { - get: function() { - return this.tokenListObserver.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(ValueListObserver.prototype, "attributeName", { - get: function() { - return this.tokenListObserver.attributeName; - }, - enumerable: true, - configurable: true - }); - ValueListObserver.prototype.tokenMatched = function(token) { - var element = token.element; - var value = this.fetchParseResultForToken(token).value; - if (value) { - this.fetchValuesByTokenForElement(element).set(token, value); - this.delegate.elementMatchedValue(element, value); - } - }; - ValueListObserver.prototype.tokenUnmatched = function(token) { - var element = token.element; - var value = this.fetchParseResultForToken(token).value; - if (value) { - this.fetchValuesByTokenForElement(element).delete(token); - this.delegate.elementUnmatchedValue(element, value); - } - }; - ValueListObserver.prototype.fetchParseResultForToken = function(token) { - var parseResult = this.parseResultsByToken.get(token); - if (!parseResult) { - parseResult = this.parseToken(token); - this.parseResultsByToken.set(token, parseResult); - } - return parseResult; - }; - ValueListObserver.prototype.fetchValuesByTokenForElement = function(element) { - var valuesByToken = this.valuesByTokenByElement.get(element); - if (!valuesByToken) { - valuesByToken = new Map(); - this.valuesByTokenByElement.set(element, valuesByToken); - } - return valuesByToken; - }; - ValueListObserver.prototype.parseToken = function(token) { - try { - var value = this.delegate.parseValueForToken(token); - return { - value: value - }; - } catch (error) { - return { - error: error - }; - } - }; - return ValueListObserver; - }(); - var BindingObserver = function() { - function BindingObserver(context, delegate) { - this.context = context; - this.delegate = delegate; - this.bindingsByAction = new Map(); - } - BindingObserver.prototype.start = function() { - if (!this.valueListObserver) { - this.valueListObserver = new ValueListObserver(this.element, this.actionAttribute, this); - this.valueListObserver.start(); - } - }; - BindingObserver.prototype.stop = function() { - if (this.valueListObserver) { - this.valueListObserver.stop(); - delete this.valueListObserver; - this.disconnectAllActions(); - } - }; - Object.defineProperty(BindingObserver.prototype, "element", { - get: function() { - return this.context.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(BindingObserver.prototype, "identifier", { - get: function() { - return this.context.identifier; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(BindingObserver.prototype, "actionAttribute", { - get: function() { - return this.schema.actionAttribute; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(BindingObserver.prototype, "schema", { - get: function() { - return this.context.schema; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(BindingObserver.prototype, "bindings", { - get: function() { - return Array.from(this.bindingsByAction.values()); - }, - enumerable: true, - configurable: true - }); - BindingObserver.prototype.connectAction = function(action) { - var binding = new Binding(this.context, action); - this.bindingsByAction.set(action, binding); - this.delegate.bindingConnected(binding); - }; - BindingObserver.prototype.disconnectAction = function(action) { - var binding = this.bindingsByAction.get(action); - if (binding) { - this.bindingsByAction.delete(action); - this.delegate.bindingDisconnected(binding); - } - }; - BindingObserver.prototype.disconnectAllActions = function() { - var _this = this; - this.bindings.forEach(function(binding) { - return _this.delegate.bindingDisconnected(binding); - }); - this.bindingsByAction.clear(); - }; - BindingObserver.prototype.parseValueForToken = function(token) { - var action = Action.forToken(token); - if (action.identifier == this.identifier) { - return action; - } - }; - BindingObserver.prototype.elementMatchedValue = function(element, action) { - this.connectAction(action); - }; - BindingObserver.prototype.elementUnmatchedValue = function(element, action) { - this.disconnectAction(action); - }; - return BindingObserver; - }(); - var Context = function() { - function Context(module, scope) { - this.module = module; - this.scope = scope; - this.controller = new module.controllerConstructor(this); - this.bindingObserver = new BindingObserver(this, this.dispatcher); - try { - this.controller.initialize(); - } catch (error) { - this.handleError(error, "initializing controller"); - } - } - Context.prototype.connect = function() { - this.bindingObserver.start(); - try { - this.controller.connect(); - } catch (error) { - this.handleError(error, "connecting controller"); - } - }; - Context.prototype.disconnect = function() { - try { - this.controller.disconnect(); - } catch (error) { - this.handleError(error, "disconnecting controller"); - } - this.bindingObserver.stop(); - }; - Object.defineProperty(Context.prototype, "application", { - get: function() { - return this.module.application; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Context.prototype, "identifier", { - get: function() { - return this.module.identifier; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Context.prototype, "schema", { - get: function() { - return this.application.schema; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Context.prototype, "dispatcher", { - get: function() { - return this.application.dispatcher; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Context.prototype, "element", { - get: function() { - return this.scope.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Context.prototype, "parentElement", { - get: function() { - return this.element.parentElement; - }, - enumerable: true, - configurable: true - }); - Context.prototype.handleError = function(error, message, detail) { - if (detail === void 0) { - detail = {}; - } - var _a = this, identifier = _a.identifier, controller = _a.controller, element = _a.element; - detail = Object.assign({ - identifier: identifier, - controller: controller, - element: element - }, detail); - this.application.handleError(error, "Error " + message, detail); - }; - return Context; - }(); - var __extends$1 = undefined && undefined.__extends || function() { - var extendStatics = Object.setPrototypeOf || { - __proto__: [] - } instanceof Array && function(d, b) { - d.__proto__ = b; - } || function(d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return function(d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; - }(); - function blessDefinition(definition) { - return { - identifier: definition.identifier, - controllerConstructor: blessControllerConstructor(definition.controllerConstructor) - }; - } - function blessControllerConstructor(controllerConstructor) { - var constructor = extend(controllerConstructor); - constructor.bless(); - return constructor; - } - var extend = function() { - function extendWithReflect(constructor) { - function Controller() { - var _newTarget = this && this instanceof Controller ? this.constructor : void 0; - return Reflect.construct(constructor, arguments, _newTarget); - } - Controller.prototype = Object.create(constructor.prototype, { - constructor: { - value: Controller - } - }); - Reflect.setPrototypeOf(Controller, constructor); - return Controller; - } - function testReflectExtension() { - var a = function() { - this.a.call(this); - }; - var b = extendWithReflect(a); - b.prototype.a = function() {}; - return new b(); - } - try { - testReflectExtension(); - return extendWithReflect; - } catch (error) { - return function(constructor) { - return function(_super) { - __extends$1(Controller, _super); - function Controller() { - return _super !== null && _super.apply(this, arguments) || this; - } - return Controller; - }(constructor); - }; - } - }(); - var Module = function() { - function Module(application, definition) { - this.application = application; - this.definition = blessDefinition(definition); - this.contextsByScope = new WeakMap(); - this.connectedContexts = new Set(); - } - Object.defineProperty(Module.prototype, "identifier", { - get: function() { - return this.definition.identifier; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Module.prototype, "controllerConstructor", { - get: function() { - return this.definition.controllerConstructor; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Module.prototype, "contexts", { - get: function() { - return Array.from(this.connectedContexts); - }, - enumerable: true, - configurable: true - }); - Module.prototype.connectContextForScope = function(scope) { - var context = this.fetchContextForScope(scope); - this.connectedContexts.add(context); - context.connect(); - }; - Module.prototype.disconnectContextForScope = function(scope) { - var context = this.contextsByScope.get(scope); - if (context) { - this.connectedContexts.delete(context); - context.disconnect(); - } - }; - Module.prototype.fetchContextForScope = function(scope) { - var context = this.contextsByScope.get(scope); - if (!context) { - context = new Context(this, scope); - this.contextsByScope.set(scope, context); - } - return context; - }; - return Module; - }(); - var DataMap = function() { - function DataMap(scope) { - this.scope = scope; - } - Object.defineProperty(DataMap.prototype, "element", { - get: function() { - return this.scope.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(DataMap.prototype, "identifier", { - get: function() { - return this.scope.identifier; - }, - enumerable: true, - configurable: true - }); - DataMap.prototype.get = function(key) { - key = this.getFormattedKey(key); - return this.element.getAttribute(key); - }; - DataMap.prototype.set = function(key, value) { - key = this.getFormattedKey(key); - this.element.setAttribute(key, value); - return this.get(key); - }; - DataMap.prototype.has = function(key) { - key = this.getFormattedKey(key); - return this.element.hasAttribute(key); - }; - DataMap.prototype.delete = function(key) { - if (this.has(key)) { - key = this.getFormattedKey(key); - this.element.removeAttribute(key); - return true; - } else { - return false; - } - }; - DataMap.prototype.getFormattedKey = function(key) { - return "data-" + this.identifier + "-" + dasherize(key); - }; - return DataMap; - }(); - function dasherize(value) { - return value.replace(/([A-Z])/g, function(_, char) { - return "-" + char.toLowerCase(); - }); - } - function attributeValueContainsToken(attributeName, token) { - return "[" + attributeName + '~="' + token + '"]'; - } - var TargetSet = function() { - function TargetSet(scope) { - this.scope = scope; - } - Object.defineProperty(TargetSet.prototype, "element", { - get: function() { - return this.scope.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(TargetSet.prototype, "identifier", { - get: function() { - return this.scope.identifier; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(TargetSet.prototype, "schema", { - get: function() { - return this.scope.schema; - }, - enumerable: true, - configurable: true - }); - TargetSet.prototype.has = function(targetName) { - return this.find(targetName) != null; - }; - TargetSet.prototype.find = function() { - var targetNames = []; - for (var _i = 0; _i < arguments.length; _i++) { - targetNames[_i] = arguments[_i]; - } - var selector = this.getSelectorForTargetNames(targetNames); - return this.scope.findElement(selector); - }; - TargetSet.prototype.findAll = function() { - var targetNames = []; - for (var _i = 0; _i < arguments.length; _i++) { - targetNames[_i] = arguments[_i]; - } - var selector = this.getSelectorForTargetNames(targetNames); - return this.scope.findAllElements(selector); - }; - TargetSet.prototype.getSelectorForTargetNames = function(targetNames) { - var _this = this; - return targetNames.map(function(targetName) { - return _this.getSelectorForTargetName(targetName); - }).join(", "); - }; - TargetSet.prototype.getSelectorForTargetName = function(targetName) { - var targetDescriptor = this.identifier + "." + targetName; - return attributeValueContainsToken(this.schema.targetAttribute, targetDescriptor); - }; - return TargetSet; - }(); - var Scope = function() { - function Scope(schema, identifier, element) { - this.schema = schema; - this.identifier = identifier; - this.element = element; - this.targets = new TargetSet(this); - this.data = new DataMap(this); - } - Scope.prototype.findElement = function(selector) { - return this.findAllElements(selector)[0]; - }; - Scope.prototype.findAllElements = function(selector) { - var head = this.element.matches(selector) ? [ this.element ] : []; - var tail = this.filterElements(Array.from(this.element.querySelectorAll(selector))); - return head.concat(tail); - }; - Scope.prototype.filterElements = function(elements) { - var _this = this; - return elements.filter(function(element) { - return _this.containsElement(element); - }); - }; - Scope.prototype.containsElement = function(element) { - return element.closest(this.controllerSelector) === this.element; - }; - Object.defineProperty(Scope.prototype, "controllerSelector", { - get: function() { - return attributeValueContainsToken(this.schema.controllerAttribute, this.identifier); - }, - enumerable: true, - configurable: true - }); - return Scope; - }(); - var ScopeObserver = function() { - function ScopeObserver(element, schema, delegate) { - this.element = element; - this.schema = schema; - this.delegate = delegate; - this.valueListObserver = new ValueListObserver(this.element, this.controllerAttribute, this); - this.scopesByIdentifierByElement = new WeakMap(); - this.scopeReferenceCounts = new WeakMap(); - } - ScopeObserver.prototype.start = function() { - this.valueListObserver.start(); - }; - ScopeObserver.prototype.stop = function() { - this.valueListObserver.stop(); - }; - Object.defineProperty(ScopeObserver.prototype, "controllerAttribute", { - get: function() { - return this.schema.controllerAttribute; - }, - enumerable: true, - configurable: true - }); - ScopeObserver.prototype.parseValueForToken = function(token) { - var element = token.element, identifier = token.content; - var scopesByIdentifier = this.fetchScopesByIdentifierForElement(element); - var scope = scopesByIdentifier.get(identifier); - if (!scope) { - scope = new Scope(this.schema, identifier, element); - scopesByIdentifier.set(identifier, scope); - } - return scope; - }; - ScopeObserver.prototype.elementMatchedValue = function(element, value) { - var referenceCount = (this.scopeReferenceCounts.get(value) || 0) + 1; - this.scopeReferenceCounts.set(value, referenceCount); - if (referenceCount == 1) { - this.delegate.scopeConnected(value); - } - }; - ScopeObserver.prototype.elementUnmatchedValue = function(element, value) { - var referenceCount = this.scopeReferenceCounts.get(value); - if (referenceCount) { - this.scopeReferenceCounts.set(value, referenceCount - 1); - if (referenceCount == 1) { - this.delegate.scopeDisconnected(value); - } - } - }; - ScopeObserver.prototype.fetchScopesByIdentifierForElement = function(element) { - var scopesByIdentifier = this.scopesByIdentifierByElement.get(element); - if (!scopesByIdentifier) { - scopesByIdentifier = new Map(); - this.scopesByIdentifierByElement.set(element, scopesByIdentifier); - } - return scopesByIdentifier; - }; - return ScopeObserver; - }(); - var Router = function() { - function Router(application) { - this.application = application; - this.scopeObserver = new ScopeObserver(this.element, this.schema, this); - this.scopesByIdentifier = new Multimap(); - this.modulesByIdentifier = new Map(); - } - Object.defineProperty(Router.prototype, "element", { - get: function() { - return this.application.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Router.prototype, "schema", { - get: function() { - return this.application.schema; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Router.prototype, "controllerAttribute", { - get: function() { - return this.schema.controllerAttribute; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Router.prototype, "modules", { - get: function() { - return Array.from(this.modulesByIdentifier.values()); - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Router.prototype, "contexts", { - get: function() { - return this.modules.reduce(function(contexts, module) { - return contexts.concat(module.contexts); - }, []); - }, - enumerable: true, - configurable: true - }); - Router.prototype.start = function() { - this.scopeObserver.start(); - }; - Router.prototype.stop = function() { - this.scopeObserver.stop(); - }; - Router.prototype.loadDefinition = function(definition) { - this.unloadIdentifier(definition.identifier); - var module = new Module(this.application, definition); - this.connectModule(module); - }; - Router.prototype.unloadIdentifier = function(identifier) { - var module = this.modulesByIdentifier.get(identifier); - if (module) { - this.disconnectModule(module); - } - }; - Router.prototype.getContextForElementAndIdentifier = function(element, identifier) { - var module = this.modulesByIdentifier.get(identifier); - if (module) { - return module.contexts.find(function(context) { - return context.element == element; - }); - } - }; - Router.prototype.handleError = function(error, message, detail) { - this.application.handleError(error, message, detail); - }; - Router.prototype.scopeConnected = function(scope) { - this.scopesByIdentifier.add(scope.identifier, scope); - var module = this.modulesByIdentifier.get(scope.identifier); - if (module) { - module.connectContextForScope(scope); - } - }; - Router.prototype.scopeDisconnected = function(scope) { - this.scopesByIdentifier.delete(scope.identifier, scope); - var module = this.modulesByIdentifier.get(scope.identifier); - if (module) { - module.disconnectContextForScope(scope); - } - }; - Router.prototype.connectModule = function(module) { - this.modulesByIdentifier.set(module.identifier, module); - var scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); - scopes.forEach(function(scope) { - return module.connectContextForScope(scope); - }); - }; - Router.prototype.disconnectModule = function(module) { - this.modulesByIdentifier.delete(module.identifier); - var scopes = this.scopesByIdentifier.getValuesForKey(module.identifier); - scopes.forEach(function(scope) { - return module.disconnectContextForScope(scope); - }); - }; - return Router; - }(); - var defaultSchema = { - controllerAttribute: "data-controller", - actionAttribute: "data-action", - targetAttribute: "data-target" - }; - var __awaiter = undefined && undefined.__awaiter || function(thisArg, _arguments, P, generator) { - return new (P || (P = Promise))(function(resolve, reject) { - function fulfilled(value) { - try { - step(generator.next(value)); - } catch (e) { - reject(e); - } - } - function rejected(value) { - try { - step(generator["throw"](value)); - } catch (e) { - reject(e); - } - } - function step(result) { - result.done ? resolve(result.value) : new P(function(resolve) { - resolve(result.value); - }).then(fulfilled, rejected); - } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); - }; - var __generator = undefined && undefined.__generator || function(thisArg, body) { - var _ = { - label: 0, - sent: function() { - if (t[0] & 1) throw t[1]; - return t[1]; - }, - trys: [], - ops: [] - }, f, y, t, g; - return g = { - next: verb(0), - throw: verb(1), - return: verb(2) - }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { - return this; - }), g; - function verb(n) { - return function(v) { - return step([ n, v ]); - }; - } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (_) try { - if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [ 0, t.value ]; - switch (op[0]) { - case 0: - case 1: - t = op; - break; - - case 4: - _.label++; - return { - value: op[1], - done: false - }; - - case 5: - _.label++; - y = op[1]; - op = [ 0 ]; - continue; - - case 7: - op = _.ops.pop(); - _.trys.pop(); - continue; - - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { - _ = 0; - continue; - } - if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) { - _.label = op[1]; - break; - } - if (op[0] === 6 && _.label < t[1]) { - _.label = t[1]; - t = op; - break; - } - if (t && _.label < t[2]) { - _.label = t[2]; - _.ops.push(op); - break; - } - if (t[2]) _.ops.pop(); - _.trys.pop(); - continue; - } - op = body.call(thisArg, _); - } catch (e) { - op = [ 6, e ]; - y = 0; - } finally { - f = t = 0; - } - if (op[0] & 5) throw op[1]; - return { - value: op[0] ? op[1] : void 0, - done: true - }; - } - }; - var Application = function() { - function Application(element, schema) { - if (element === void 0) { - element = document.documentElement; - } - if (schema === void 0) { - schema = defaultSchema; - } - this.element = element; - this.schema = schema; - this.dispatcher = new Dispatcher(this); - this.router = new Router(this); - } - Application.start = function(element, schema) { - var application = new Application(element, schema); - application.start(); - return application; - }; - Application.prototype.start = function() { - return __awaiter(this, void 0, void 0, function() { - return __generator(this, function(_a) { - switch (_a.label) { - case 0: - return [ 4, domReady() ]; - - case 1: - _a.sent(); - this.router.start(); - this.dispatcher.start(); - return [ 2 ]; - } - }); - }); - }; - Application.prototype.stop = function() { - this.router.stop(); - this.dispatcher.stop(); - }; - Application.prototype.register = function(identifier, controllerConstructor) { - this.load({ - identifier: identifier, - controllerConstructor: controllerConstructor - }); - }; - Application.prototype.load = function(head) { - var _this = this; - var rest = []; - for (var _i = 1; _i < arguments.length; _i++) { - rest[_i - 1] = arguments[_i]; - } - var definitions = Array.isArray(head) ? head : [ head ].concat(rest); - definitions.forEach(function(definition) { - return _this.router.loadDefinition(definition); - }); - }; - Application.prototype.unload = function(head) { - var _this = this; - var rest = []; - for (var _i = 1; _i < arguments.length; _i++) { - rest[_i - 1] = arguments[_i]; - } - var identifiers = Array.isArray(head) ? head : [ head ].concat(rest); - identifiers.forEach(function(identifier) { - return _this.router.unloadIdentifier(identifier); - }); - }; - Object.defineProperty(Application.prototype, "controllers", { - get: function() { - return this.router.contexts.map(function(context) { - return context.controller; - }); - }, - enumerable: true, - configurable: true - }); - Application.prototype.getControllerForElementAndIdentifier = function(element, identifier) { - var context = this.router.getContextForElementAndIdentifier(element, identifier); - return context ? context.controller : null; - }; - Application.prototype.handleError = function(error, message, detail) { - console.error("%s\n\n%o\n\n%o", message, error, detail); - }; - return Application; - }(); - function domReady() { - return new Promise(function(resolve) { - if (document.readyState == "loading") { - document.addEventListener("DOMContentLoaded", resolve); - } else { - resolve(); - } - }); - } - function defineTargetProperties(constructor) { - var prototype = constructor.prototype; - var targetNames = getTargetNamesForConstructor(constructor); - targetNames.forEach(function(name) { - var _a; - return defineLinkedProperties(prototype, (_a = {}, _a[name + "Target"] = { - get: function() { - var target = this.targets.find(name); - if (target) { - return target; - } else { - throw new Error('Missing target element "' + this.identifier + "." + name + '"'); - } - } - }, _a[name + "Targets"] = { - get: function() { - return this.targets.findAll(name); - } - }, _a["has" + capitalize(name) + "Target"] = { - get: function() { - return this.targets.has(name); - } - }, _a)); - }); - } - function getTargetNamesForConstructor(constructor) { - var ancestors = getAncestorsForConstructor(constructor); - return Array.from(ancestors.reduce(function(targetNames, constructor) { - getOwnTargetNamesForConstructor(constructor).forEach(function(name) { - return targetNames.add(name); - }); - return targetNames; - }, new Set())); - } - function getAncestorsForConstructor(constructor) { - var ancestors = []; - while (constructor) { - ancestors.push(constructor); - constructor = Object.getPrototypeOf(constructor); - } - return ancestors; - } - function getOwnTargetNamesForConstructor(constructor) { - var definition = constructor["targets"]; - return Array.isArray(definition) ? definition : []; - } - function defineLinkedProperties(object, properties) { - Object.keys(properties).forEach(function(name) { - if (!(name in object)) { - var descriptor = properties[name]; - Object.defineProperty(object, name, descriptor); - } - }); - } - function capitalize(name) { - return name.charAt(0).toUpperCase() + name.slice(1); - } - var Controller = function() { - function Controller(context) { - this.context = context; - } - Controller.bless = function() { - defineTargetProperties(this); - }; - Object.defineProperty(Controller.prototype, "application", { - get: function() { - return this.context.application; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Controller.prototype, "scope", { - get: function() { - return this.context.scope; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Controller.prototype, "element", { - get: function() { - return this.scope.element; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Controller.prototype, "identifier", { - get: function() { - return this.scope.identifier; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Controller.prototype, "targets", { - get: function() { - return this.scope.targets; - }, - enumerable: true, - configurable: true - }); - Object.defineProperty(Controller.prototype, "data", { - get: function() { - return this.scope.data; - }, - enumerable: true, - configurable: true - }); - Controller.prototype.initialize = function() {}; - Controller.prototype.connect = function() {}; - Controller.prototype.disconnect = function() {}; - Controller.targets = []; - return Controller; - }(); - exports.Application = Application; - exports.Context = Context; - exports.Controller = Controller; - exports.defaultSchema = defaultSchema; - Object.defineProperty(exports, "__esModule", { - value: true - }); -}); - - -; - -/** - * @popperjs/core v2.8.4 - MIT License - */ - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : - typeof define === 'function' && define.amd ? define(['exports'], factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Popper = {})); -}(this, (function (exports) { 'use strict'; - - function getBoundingClientRect(element) { - var rect = element.getBoundingClientRect(); - return { - width: rect.width, - height: rect.height, - top: rect.top, - right: rect.right, - bottom: rect.bottom, - left: rect.left, - x: rect.left, - y: rect.top - }; - } - - /*:: import type { Window } from '../types'; */ - - /*:: declare function getWindow(node: Node | Window): Window; */ - function getWindow(node) { - if (node.toString() !== '[object Window]') { - var ownerDocument = node.ownerDocument; - return ownerDocument ? ownerDocument.defaultView || window : window; - } - - return node; - } - - function getWindowScroll(node) { - var win = getWindow(node); - var scrollLeft = win.pageXOffset; - var scrollTop = win.pageYOffset; - return { - scrollLeft: scrollLeft, - scrollTop: scrollTop - }; - } - - /*:: declare function isElement(node: mixed): boolean %checks(node instanceof - Element); */ - - function isElement(node) { - var OwnElement = getWindow(node).Element; - return node instanceof OwnElement || node instanceof Element; - } - /*:: declare function isHTMLElement(node: mixed): boolean %checks(node instanceof - HTMLElement); */ - - - function isHTMLElement(node) { - var OwnElement = getWindow(node).HTMLElement; - return node instanceof OwnElement || node instanceof HTMLElement; - } - /*:: declare function isShadowRoot(node: mixed): boolean %checks(node instanceof - ShadowRoot); */ - - - function isShadowRoot(node) { - // IE 11 has no ShadowRoot - if (typeof ShadowRoot === 'undefined') { - return false; - } - - var OwnElement = getWindow(node).ShadowRoot; - return node instanceof OwnElement || node instanceof ShadowRoot; - } - - function getHTMLElementScroll(element) { - return { - scrollLeft: element.scrollLeft, - scrollTop: element.scrollTop - }; - } - - function getNodeScroll(node) { - if (node === getWindow(node) || !isHTMLElement(node)) { - return getWindowScroll(node); - } else { - return getHTMLElementScroll(node); - } - } - - function getNodeName(element) { - return element ? (element.nodeName || '').toLowerCase() : null; - } - - function getDocumentElement(element) { - // $FlowFixMe[incompatible-return]: assume body is always available - return ((isElement(element) ? element.ownerDocument : // $FlowFixMe[prop-missing] - element.document) || window.document).documentElement; - } - - function getWindowScrollBarX(element) { - // If has a CSS width greater than the viewport, then this will be - // incorrect for RTL. - // Popper 1 is broken in this case and never had a bug report so let's assume - // it's not an issue. I don't think anyone ever specifies width on - // anyway. - // Browsers where the left scrollbar doesn't cause an issue report `0` for - // this (e.g. Edge 2019, IE11, Safari) - return getBoundingClientRect(getDocumentElement(element)).left + getWindowScroll(element).scrollLeft; - } - - function getComputedStyle(element) { - return getWindow(element).getComputedStyle(element); - } - - function isScrollParent(element) { - // Firefox wants us to check `-x` and `-y` variations as well - var _getComputedStyle = getComputedStyle(element), - overflow = _getComputedStyle.overflow, - overflowX = _getComputedStyle.overflowX, - overflowY = _getComputedStyle.overflowY; - - return /auto|scroll|overlay|hidden/.test(overflow + overflowY + overflowX); - } - - // Composite means it takes into account transforms as well as layout. - - function getCompositeRect(elementOrVirtualElement, offsetParent, isFixed) { - if (isFixed === void 0) { - isFixed = false; - } - - var documentElement = getDocumentElement(offsetParent); - var rect = getBoundingClientRect(elementOrVirtualElement); - var isOffsetParentAnElement = isHTMLElement(offsetParent); - var scroll = { - scrollLeft: 0, - scrollTop: 0 - }; - var offsets = { - x: 0, - y: 0 - }; - - if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { - if (getNodeName(offsetParent) !== 'body' || // https://github.com/popperjs/popper-core/issues/1078 - isScrollParent(documentElement)) { - scroll = getNodeScroll(offsetParent); - } - - if (isHTMLElement(offsetParent)) { - offsets = getBoundingClientRect(offsetParent); - offsets.x += offsetParent.clientLeft; - offsets.y += offsetParent.clientTop; - } else if (documentElement) { - offsets.x = getWindowScrollBarX(documentElement); - } - } - - return { - x: rect.left + scroll.scrollLeft - offsets.x, - y: rect.top + scroll.scrollTop - offsets.y, - width: rect.width, - height: rect.height - }; - } - - // Returns the layout rect of an element relative to its offsetParent. Layout - // means it doesn't take into account transforms. - function getLayoutRect(element) { - return { - x: element.offsetLeft, - y: element.offsetTop, - width: element.offsetWidth, - height: element.offsetHeight - }; - } - - function getParentNode(element) { - if (getNodeName(element) === 'html') { - return element; - } - - return (// this is a quicker (but less type safe) way to save quite some bytes from the bundle - // $FlowFixMe[incompatible-return] - // $FlowFixMe[prop-missing] - element.assignedSlot || // step into the shadow DOM of the parent of a slotted node - element.parentNode || ( // DOM Element detected - isShadowRoot(element) ? element.host : null) || // ShadowRoot detected - // $FlowFixMe[incompatible-call]: HTMLElement is a Node - getDocumentElement(element) // fallback - - ); - } - - function getScrollParent(node) { - if (['html', 'body', '#document'].indexOf(getNodeName(node)) >= 0) { - // $FlowFixMe[incompatible-return]: assume body is always available - return node.ownerDocument.body; - } - - if (isHTMLElement(node) && isScrollParent(node)) { - return node; - } - - return getScrollParent(getParentNode(node)); - } - - /* - given a DOM element, return the list of all scroll parents, up the list of ancesors - until we get to the top window object. This list is what we attach scroll listeners - to, because if any of these parent elements scroll, we'll need to re-calculate the - reference element's position. - */ - - function listScrollParents(element, list) { - var _element$ownerDocumen; - - if (list === void 0) { - list = []; - } - - var scrollParent = getScrollParent(element); - var isBody = scrollParent === ((_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body); - var win = getWindow(scrollParent); - var target = isBody ? [win].concat(win.visualViewport || [], isScrollParent(scrollParent) ? scrollParent : []) : scrollParent; - var updatedList = list.concat(target); - return isBody ? updatedList : // $FlowFixMe[incompatible-call]: isBody tells us target will be an HTMLElement here - updatedList.concat(listScrollParents(getParentNode(target))); - } - - function isTableElement(element) { - return ['table', 'td', 'th'].indexOf(getNodeName(element)) >= 0; - } - - function getTrueOffsetParent(element) { - if (!isHTMLElement(element) || // https://github.com/popperjs/popper-core/issues/837 - getComputedStyle(element).position === 'fixed') { - return null; - } - - return element.offsetParent; - } // `.offsetParent` reports `null` for fixed elements, while absolute elements - // return the containing block - - - function getContainingBlock(element) { - var isFirefox = navigator.userAgent.toLowerCase().includes('firefox'); - var currentNode = getParentNode(element); - - while (isHTMLElement(currentNode) && ['html', 'body'].indexOf(getNodeName(currentNode)) < 0) { - var css = getComputedStyle(currentNode); // This is non-exhaustive but covers the most common CSS properties that - // create a containing block. - // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block - - if (css.transform !== 'none' || css.perspective !== 'none' || css.contain === 'paint' || ['transform', 'perspective'].includes(css.willChange) || isFirefox && css.willChange === 'filter' || isFirefox && css.filter && css.filter !== 'none') { - return currentNode; - } else { - currentNode = currentNode.parentNode; - } - } - - return null; - } // Gets the closest ancestor positioned element. Handles some edge cases, - // such as table ancestors and cross browser bugs. - - - function getOffsetParent(element) { - var window = getWindow(element); - var offsetParent = getTrueOffsetParent(element); - - while (offsetParent && isTableElement(offsetParent) && getComputedStyle(offsetParent).position === 'static') { - offsetParent = getTrueOffsetParent(offsetParent); - } - - if (offsetParent && (getNodeName(offsetParent) === 'html' || getNodeName(offsetParent) === 'body' && getComputedStyle(offsetParent).position === 'static')) { - return window; - } - - return offsetParent || getContainingBlock(element) || window; - } - - var top = 'top'; - var bottom = 'bottom'; - var right = 'right'; - var left = 'left'; - var auto = 'auto'; - var basePlacements = [top, bottom, right, left]; - var start = 'start'; - var end = 'end'; - var clippingParents = 'clippingParents'; - var viewport = 'viewport'; - var popper = 'popper'; - var reference = 'reference'; - var variationPlacements = /*#__PURE__*/basePlacements.reduce(function (acc, placement) { - return acc.concat([placement + "-" + start, placement + "-" + end]); - }, []); - var placements = /*#__PURE__*/[].concat(basePlacements, [auto]).reduce(function (acc, placement) { - return acc.concat([placement, placement + "-" + start, placement + "-" + end]); - }, []); // modifiers that need to read the DOM - - var beforeRead = 'beforeRead'; - var read = 'read'; - var afterRead = 'afterRead'; // pure-logic modifiers - - var beforeMain = 'beforeMain'; - var main = 'main'; - var afterMain = 'afterMain'; // modifier with the purpose to write to the DOM (or write into a framework state) - - var beforeWrite = 'beforeWrite'; - var write = 'write'; - var afterWrite = 'afterWrite'; - var modifierPhases = [beforeRead, read, afterRead, beforeMain, main, afterMain, beforeWrite, write, afterWrite]; - - function order(modifiers) { - var map = new Map(); - var visited = new Set(); - var result = []; - modifiers.forEach(function (modifier) { - map.set(modifier.name, modifier); - }); // On visiting object, check for its dependencies and visit them recursively - - function sort(modifier) { - visited.add(modifier.name); - var requires = [].concat(modifier.requires || [], modifier.requiresIfExists || []); - requires.forEach(function (dep) { - if (!visited.has(dep)) { - var depModifier = map.get(dep); - - if (depModifier) { - sort(depModifier); - } - } - }); - result.push(modifier); - } - - modifiers.forEach(function (modifier) { - if (!visited.has(modifier.name)) { - // check for visited object - sort(modifier); - } - }); - return result; - } - - function orderModifiers(modifiers) { - // order based on dependencies - var orderedModifiers = order(modifiers); // order based on phase - - return modifierPhases.reduce(function (acc, phase) { - return acc.concat(orderedModifiers.filter(function (modifier) { - return modifier.phase === phase; - })); - }, []); - } - - function debounce(fn) { - var pending; - return function () { - if (!pending) { - pending = new Promise(function (resolve) { - Promise.resolve().then(function () { - pending = undefined; - resolve(fn()); - }); - }); - } - - return pending; - }; - } - - function format(str) { - for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - return [].concat(args).reduce(function (p, c) { - return p.replace(/%s/, c); - }, str); - } - - var INVALID_MODIFIER_ERROR = 'Popper: modifier "%s" provided an invalid %s property, expected %s but got %s'; - var MISSING_DEPENDENCY_ERROR = 'Popper: modifier "%s" requires "%s", but "%s" modifier is not available'; - var VALID_PROPERTIES = ['name', 'enabled', 'phase', 'fn', 'effect', 'requires', 'options']; - function validateModifiers(modifiers) { - modifiers.forEach(function (modifier) { - Object.keys(modifier).forEach(function (key) { - switch (key) { - case 'name': - if (typeof modifier.name !== 'string') { - console.error(format(INVALID_MODIFIER_ERROR, String(modifier.name), '"name"', '"string"', "\"" + String(modifier.name) + "\"")); - } - - break; - - case 'enabled': - if (typeof modifier.enabled !== 'boolean') { - console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"enabled"', '"boolean"', "\"" + String(modifier.enabled) + "\"")); - } - - case 'phase': - if (modifierPhases.indexOf(modifier.phase) < 0) { - console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"phase"', "either " + modifierPhases.join(', '), "\"" + String(modifier.phase) + "\"")); - } - - break; - - case 'fn': - if (typeof modifier.fn !== 'function') { - console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"fn"', '"function"', "\"" + String(modifier.fn) + "\"")); - } - - break; - - case 'effect': - if (typeof modifier.effect !== 'function') { - console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"effect"', '"function"', "\"" + String(modifier.fn) + "\"")); - } - - break; - - case 'requires': - if (!Array.isArray(modifier.requires)) { - console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requires"', '"array"', "\"" + String(modifier.requires) + "\"")); - } - - break; - - case 'requiresIfExists': - if (!Array.isArray(modifier.requiresIfExists)) { - console.error(format(INVALID_MODIFIER_ERROR, modifier.name, '"requiresIfExists"', '"array"', "\"" + String(modifier.requiresIfExists) + "\"")); - } - - break; - - case 'options': - case 'data': - break; - - default: - console.error("PopperJS: an invalid property has been provided to the \"" + modifier.name + "\" modifier, valid properties are " + VALID_PROPERTIES.map(function (s) { - return "\"" + s + "\""; - }).join(', ') + "; but \"" + key + "\" was provided."); - } - - modifier.requires && modifier.requires.forEach(function (requirement) { - if (modifiers.find(function (mod) { - return mod.name === requirement; - }) == null) { - console.error(format(MISSING_DEPENDENCY_ERROR, String(modifier.name), requirement, requirement)); - } - }); - }); - }); - } - - function uniqueBy(arr, fn) { - var identifiers = new Set(); - return arr.filter(function (item) { - var identifier = fn(item); - - if (!identifiers.has(identifier)) { - identifiers.add(identifier); - return true; - } - }); - } - - function getBasePlacement(placement) { - return placement.split('-')[0]; - } - - function mergeByName(modifiers) { - var merged = modifiers.reduce(function (merged, current) { - var existing = merged[current.name]; - merged[current.name] = existing ? Object.assign({}, existing, current, { - options: Object.assign({}, existing.options, current.options), - data: Object.assign({}, existing.data, current.data) - }) : current; - return merged; - }, {}); // IE11 does not support Object.values - - return Object.keys(merged).map(function (key) { - return merged[key]; - }); - } - - function getViewportRect(element) { - var win = getWindow(element); - var html = getDocumentElement(element); - var visualViewport = win.visualViewport; - var width = html.clientWidth; - var height = html.clientHeight; - var x = 0; - var y = 0; // NB: This isn't supported on iOS <= 12. If the keyboard is open, the popper - // can be obscured underneath it. - // Also, `html.clientHeight` adds the bottom bar height in Safari iOS, even - // if it isn't open, so if this isn't available, the popper will be detected - // to overflow the bottom of the screen too early. - - if (visualViewport) { - width = visualViewport.width; - height = visualViewport.height; // Uses Layout Viewport (like Chrome; Safari does not currently) - // In Chrome, it returns a value very close to 0 (+/-) but contains rounding - // errors due to floating point numbers, so we need to check precision. - // Safari returns a number <= 0, usually < -1 when pinch-zoomed - // Feature detection fails in mobile emulation mode in Chrome. - // Math.abs(win.innerWidth / visualViewport.scale - visualViewport.width) < - // 0.001 - // Fallback here: "Not Safari" userAgent - - if (!/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) { - x = visualViewport.offsetLeft; - y = visualViewport.offsetTop; - } - } - - return { - width: width, - height: height, - x: x + getWindowScrollBarX(element), - y: y - }; - } - - var max = Math.max; - var min = Math.min; - var round = Math.round; - - // of the `` and `` rect bounds if horizontally scrollable - - function getDocumentRect(element) { - var _element$ownerDocumen; - - var html = getDocumentElement(element); - var winScroll = getWindowScroll(element); - var body = (_element$ownerDocumen = element.ownerDocument) == null ? void 0 : _element$ownerDocumen.body; - var width = max(html.scrollWidth, html.clientWidth, body ? body.scrollWidth : 0, body ? body.clientWidth : 0); - var height = max(html.scrollHeight, html.clientHeight, body ? body.scrollHeight : 0, body ? body.clientHeight : 0); - var x = -winScroll.scrollLeft + getWindowScrollBarX(element); - var y = -winScroll.scrollTop; - - if (getComputedStyle(body || html).direction === 'rtl') { - x += max(html.clientWidth, body ? body.clientWidth : 0) - width; - } - - return { - width: width, - height: height, - x: x, - y: y - }; - } - - function contains(parent, child) { - var rootNode = child.getRootNode && child.getRootNode(); // First, attempt with faster native method - - if (parent.contains(child)) { - return true; - } // then fallback to custom implementation with Shadow DOM support - else if (rootNode && isShadowRoot(rootNode)) { - var next = child; - - do { - if (next && parent.isSameNode(next)) { - return true; - } // $FlowFixMe[prop-missing]: need a better way to handle this... - - - next = next.parentNode || next.host; - } while (next); - } // Give up, the result is false - - - return false; - } - - function rectToClientRect(rect) { - return Object.assign({}, rect, { - left: rect.x, - top: rect.y, - right: rect.x + rect.width, - bottom: rect.y + rect.height - }); - } - - function getInnerBoundingClientRect(element) { - var rect = getBoundingClientRect(element); - rect.top = rect.top + element.clientTop; - rect.left = rect.left + element.clientLeft; - rect.bottom = rect.top + element.clientHeight; - rect.right = rect.left + element.clientWidth; - rect.width = element.clientWidth; - rect.height = element.clientHeight; - rect.x = rect.left; - rect.y = rect.top; - return rect; - } - - function getClientRectFromMixedType(element, clippingParent) { - return clippingParent === viewport ? rectToClientRect(getViewportRect(element)) : isHTMLElement(clippingParent) ? getInnerBoundingClientRect(clippingParent) : rectToClientRect(getDocumentRect(getDocumentElement(element))); - } // A "clipping parent" is an overflowable container with the characteristic of - // clipping (or hiding) overflowing elements with a position different from - // `initial` - - - function getClippingParents(element) { - var clippingParents = listScrollParents(getParentNode(element)); - var canEscapeClipping = ['absolute', 'fixed'].indexOf(getComputedStyle(element).position) >= 0; - var clipperElement = canEscapeClipping && isHTMLElement(element) ? getOffsetParent(element) : element; - - if (!isElement(clipperElement)) { - return []; - } // $FlowFixMe[incompatible-return]: https://github.com/facebook/flow/issues/1414 - - - return clippingParents.filter(function (clippingParent) { - return isElement(clippingParent) && contains(clippingParent, clipperElement) && getNodeName(clippingParent) !== 'body'; - }); - } // Gets the maximum area that the element is visible in due to any number of - // clipping parents - - - function getClippingRect(element, boundary, rootBoundary) { - var mainClippingParents = boundary === 'clippingParents' ? getClippingParents(element) : [].concat(boundary); - var clippingParents = [].concat(mainClippingParents, [rootBoundary]); - var firstClippingParent = clippingParents[0]; - var clippingRect = clippingParents.reduce(function (accRect, clippingParent) { - var rect = getClientRectFromMixedType(element, clippingParent); - accRect.top = max(rect.top, accRect.top); - accRect.right = min(rect.right, accRect.right); - accRect.bottom = min(rect.bottom, accRect.bottom); - accRect.left = max(rect.left, accRect.left); - return accRect; - }, getClientRectFromMixedType(element, firstClippingParent)); - clippingRect.width = clippingRect.right - clippingRect.left; - clippingRect.height = clippingRect.bottom - clippingRect.top; - clippingRect.x = clippingRect.left; - clippingRect.y = clippingRect.top; - return clippingRect; - } - - function getVariation(placement) { - return placement.split('-')[1]; - } - - function getMainAxisFromPlacement(placement) { - return ['top', 'bottom'].indexOf(placement) >= 0 ? 'x' : 'y'; - } - - function computeOffsets(_ref) { - var reference = _ref.reference, - element = _ref.element, - placement = _ref.placement; - var basePlacement = placement ? getBasePlacement(placement) : null; - var variation = placement ? getVariation(placement) : null; - var commonX = reference.x + reference.width / 2 - element.width / 2; - var commonY = reference.y + reference.height / 2 - element.height / 2; - var offsets; - - switch (basePlacement) { - case top: - offsets = { - x: commonX, - y: reference.y - element.height - }; - break; - - case bottom: - offsets = { - x: commonX, - y: reference.y + reference.height - }; - break; - - case right: - offsets = { - x: reference.x + reference.width, - y: commonY - }; - break; - - case left: - offsets = { - x: reference.x - element.width, - y: commonY - }; - break; - - default: - offsets = { - x: reference.x, - y: reference.y - }; - } - - var mainAxis = basePlacement ? getMainAxisFromPlacement(basePlacement) : null; - - if (mainAxis != null) { - var len = mainAxis === 'y' ? 'height' : 'width'; - - switch (variation) { - case start: - offsets[mainAxis] = offsets[mainAxis] - (reference[len] / 2 - element[len] / 2); - break; - - case end: - offsets[mainAxis] = offsets[mainAxis] + (reference[len] / 2 - element[len] / 2); - break; - } - } - - return offsets; - } - - function getFreshSideObject() { - return { - top: 0, - right: 0, - bottom: 0, - left: 0 - }; - } - - function mergePaddingObject(paddingObject) { - return Object.assign({}, getFreshSideObject(), paddingObject); - } - - function expandToHashMap(value, keys) { - return keys.reduce(function (hashMap, key) { - hashMap[key] = value; - return hashMap; - }, {}); - } - - function detectOverflow(state, options) { - if (options === void 0) { - options = {}; - } - - var _options = options, - _options$placement = _options.placement, - placement = _options$placement === void 0 ? state.placement : _options$placement, - _options$boundary = _options.boundary, - boundary = _options$boundary === void 0 ? clippingParents : _options$boundary, - _options$rootBoundary = _options.rootBoundary, - rootBoundary = _options$rootBoundary === void 0 ? viewport : _options$rootBoundary, - _options$elementConte = _options.elementContext, - elementContext = _options$elementConte === void 0 ? popper : _options$elementConte, - _options$altBoundary = _options.altBoundary, - altBoundary = _options$altBoundary === void 0 ? false : _options$altBoundary, - _options$padding = _options.padding, - padding = _options$padding === void 0 ? 0 : _options$padding; - var paddingObject = mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); - var altContext = elementContext === popper ? reference : popper; - var referenceElement = state.elements.reference; - var popperRect = state.rects.popper; - var element = state.elements[altBoundary ? altContext : elementContext]; - var clippingClientRect = getClippingRect(isElement(element) ? element : element.contextElement || getDocumentElement(state.elements.popper), boundary, rootBoundary); - var referenceClientRect = getBoundingClientRect(referenceElement); - var popperOffsets = computeOffsets({ - reference: referenceClientRect, - element: popperRect, - strategy: 'absolute', - placement: placement - }); - var popperClientRect = rectToClientRect(Object.assign({}, popperRect, popperOffsets)); - var elementClientRect = elementContext === popper ? popperClientRect : referenceClientRect; // positive = overflowing the clipping rect - // 0 or negative = within the clipping rect - - var overflowOffsets = { - top: clippingClientRect.top - elementClientRect.top + paddingObject.top, - bottom: elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom, - left: clippingClientRect.left - elementClientRect.left + paddingObject.left, - right: elementClientRect.right - clippingClientRect.right + paddingObject.right - }; - var offsetData = state.modifiersData.offset; // Offsets can be applied only to the popper element - - if (elementContext === popper && offsetData) { - var offset = offsetData[placement]; - Object.keys(overflowOffsets).forEach(function (key) { - var multiply = [right, bottom].indexOf(key) >= 0 ? 1 : -1; - var axis = [top, bottom].indexOf(key) >= 0 ? 'y' : 'x'; - overflowOffsets[key] += offset[axis] * multiply; - }); - } - - return overflowOffsets; - } - - var INVALID_ELEMENT_ERROR = 'Popper: Invalid reference or popper argument provided. They must be either a DOM element or virtual element.'; - var INFINITE_LOOP_ERROR = 'Popper: An infinite loop in the modifiers cycle has been detected! The cycle has been interrupted to prevent a browser crash.'; - var DEFAULT_OPTIONS = { - placement: 'bottom', - modifiers: [], - strategy: 'absolute' - }; - - function areValidElements() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - return !args.some(function (element) { - return !(element && typeof element.getBoundingClientRect === 'function'); - }); - } - - function popperGenerator(generatorOptions) { - if (generatorOptions === void 0) { - generatorOptions = {}; - } - - var _generatorOptions = generatorOptions, - _generatorOptions$def = _generatorOptions.defaultModifiers, - defaultModifiers = _generatorOptions$def === void 0 ? [] : _generatorOptions$def, - _generatorOptions$def2 = _generatorOptions.defaultOptions, - defaultOptions = _generatorOptions$def2 === void 0 ? DEFAULT_OPTIONS : _generatorOptions$def2; - return function createPopper(reference, popper, options) { - if (options === void 0) { - options = defaultOptions; - } - - var state = { - placement: 'bottom', - orderedModifiers: [], - options: Object.assign({}, DEFAULT_OPTIONS, defaultOptions), - modifiersData: {}, - elements: { - reference: reference, - popper: popper - }, - attributes: {}, - styles: {} - }; - var effectCleanupFns = []; - var isDestroyed = false; - var instance = { - state: state, - setOptions: function setOptions(options) { - cleanupModifierEffects(); - state.options = Object.assign({}, defaultOptions, state.options, options); - state.scrollParents = { - reference: isElement(reference) ? listScrollParents(reference) : reference.contextElement ? listScrollParents(reference.contextElement) : [], - popper: listScrollParents(popper) - }; // Orders the modifiers based on their dependencies and `phase` - // properties - - var orderedModifiers = orderModifiers(mergeByName([].concat(defaultModifiers, state.options.modifiers))); // Strip out disabled modifiers - - state.orderedModifiers = orderedModifiers.filter(function (m) { - return m.enabled; - }); // Validate the provided modifiers so that the consumer will get warned - // if one of the modifiers is invalid for any reason - - { - var modifiers = uniqueBy([].concat(orderedModifiers, state.options.modifiers), function (_ref) { - var name = _ref.name; - return name; - }); - validateModifiers(modifiers); - - if (getBasePlacement(state.options.placement) === auto) { - var flipModifier = state.orderedModifiers.find(function (_ref2) { - var name = _ref2.name; - return name === 'flip'; - }); - - if (!flipModifier) { - console.error(['Popper: "auto" placements require the "flip" modifier be', 'present and enabled to work.'].join(' ')); - } - } - - var _getComputedStyle = getComputedStyle(popper), - marginTop = _getComputedStyle.marginTop, - marginRight = _getComputedStyle.marginRight, - marginBottom = _getComputedStyle.marginBottom, - marginLeft = _getComputedStyle.marginLeft; // We no longer take into account `margins` on the popper, and it can - // cause bugs with positioning, so we'll warn the consumer - - - if ([marginTop, marginRight, marginBottom, marginLeft].some(function (margin) { - return parseFloat(margin); - })) { - console.warn(['Popper: CSS "margin" styles cannot be used to apply padding', 'between the popper and its reference element or boundary.', 'To replicate margin, use the `offset` modifier, as well as', 'the `padding` option in the `preventOverflow` and `flip`', 'modifiers.'].join(' ')); - } - } - - runModifierEffects(); - return instance.update(); - }, - // Sync update – it will always be executed, even if not necessary. This - // is useful for low frequency updates where sync behavior simplifies the - // logic. - // For high frequency updates (e.g. `resize` and `scroll` events), always - // prefer the async Popper#update method - forceUpdate: function forceUpdate() { - if (isDestroyed) { - return; - } - - var _state$elements = state.elements, - reference = _state$elements.reference, - popper = _state$elements.popper; // Don't proceed if `reference` or `popper` are not valid elements - // anymore - - if (!areValidElements(reference, popper)) { - { - console.error(INVALID_ELEMENT_ERROR); - } - - return; - } // Store the reference and popper rects to be read by modifiers - - - state.rects = { - reference: getCompositeRect(reference, getOffsetParent(popper), state.options.strategy === 'fixed'), - popper: getLayoutRect(popper) - }; // Modifiers have the ability to reset the current update cycle. The - // most common use case for this is the `flip` modifier changing the - // placement, which then needs to re-run all the modifiers, because the - // logic was previously ran for the previous placement and is therefore - // stale/incorrect - - state.reset = false; - state.placement = state.options.placement; // On each update cycle, the `modifiersData` property for each modifier - // is filled with the initial data specified by the modifier. This means - // it doesn't persist and is fresh on each update. - // To ensure persistent data, use `${name}#persistent` - - state.orderedModifiers.forEach(function (modifier) { - return state.modifiersData[modifier.name] = Object.assign({}, modifier.data); - }); - var __debug_loops__ = 0; - - for (var index = 0; index < state.orderedModifiers.length; index++) { - { - __debug_loops__ += 1; - - if (__debug_loops__ > 100) { - console.error(INFINITE_LOOP_ERROR); - break; - } - } - - if (state.reset === true) { - state.reset = false; - index = -1; - continue; - } - - var _state$orderedModifie = state.orderedModifiers[index], - fn = _state$orderedModifie.fn, - _state$orderedModifie2 = _state$orderedModifie.options, - _options = _state$orderedModifie2 === void 0 ? {} : _state$orderedModifie2, - name = _state$orderedModifie.name; - - if (typeof fn === 'function') { - state = fn({ - state: state, - options: _options, - name: name, - instance: instance - }) || state; - } - } - }, - // Async and optimistically optimized update – it will not be executed if - // not necessary (debounced to run at most once-per-tick) - update: debounce(function () { - return new Promise(function (resolve) { - instance.forceUpdate(); - resolve(state); - }); - }), - destroy: function destroy() { - cleanupModifierEffects(); - isDestroyed = true; - } - }; - - if (!areValidElements(reference, popper)) { - { - console.error(INVALID_ELEMENT_ERROR); - } - - return instance; - } - - instance.setOptions(options).then(function (state) { - if (!isDestroyed && options.onFirstUpdate) { - options.onFirstUpdate(state); - } - }); // Modifiers have the ability to execute arbitrary code before the first - // update cycle runs. They will be executed in the same order as the update - // cycle. This is useful when a modifier adds some persistent data that - // other modifiers need to use, but the modifier is run after the dependent - // one. - - function runModifierEffects() { - state.orderedModifiers.forEach(function (_ref3) { - var name = _ref3.name, - _ref3$options = _ref3.options, - options = _ref3$options === void 0 ? {} : _ref3$options, - effect = _ref3.effect; - - if (typeof effect === 'function') { - var cleanupFn = effect({ - state: state, - name: name, - instance: instance, - options: options - }); - - var noopFn = function noopFn() {}; - - effectCleanupFns.push(cleanupFn || noopFn); - } - }); - } - - function cleanupModifierEffects() { - effectCleanupFns.forEach(function (fn) { - return fn(); - }); - effectCleanupFns = []; - } - - return instance; - }; - } - - var passive = { - passive: true - }; - - function effect(_ref) { - var state = _ref.state, - instance = _ref.instance, - options = _ref.options; - var _options$scroll = options.scroll, - scroll = _options$scroll === void 0 ? true : _options$scroll, - _options$resize = options.resize, - resize = _options$resize === void 0 ? true : _options$resize; - var window = getWindow(state.elements.popper); - var scrollParents = [].concat(state.scrollParents.reference, state.scrollParents.popper); - - if (scroll) { - scrollParents.forEach(function (scrollParent) { - scrollParent.addEventListener('scroll', instance.update, passive); - }); - } - - if (resize) { - window.addEventListener('resize', instance.update, passive); - } - - return function () { - if (scroll) { - scrollParents.forEach(function (scrollParent) { - scrollParent.removeEventListener('scroll', instance.update, passive); - }); - } - - if (resize) { - window.removeEventListener('resize', instance.update, passive); - } - }; - } // eslint-disable-next-line import/no-unused-modules - - - var eventListeners = { - name: 'eventListeners', - enabled: true, - phase: 'write', - fn: function fn() {}, - effect: effect, - data: {} - }; - - function popperOffsets(_ref) { - var state = _ref.state, - name = _ref.name; - // Offsets are the actual position the popper needs to have to be - // properly positioned near its reference element - // This is the most basic placement, and will be adjusted by - // the modifiers in the next step - state.modifiersData[name] = computeOffsets({ - reference: state.rects.reference, - element: state.rects.popper, - strategy: 'absolute', - placement: state.placement - }); - } // eslint-disable-next-line import/no-unused-modules - - - var popperOffsets$1 = { - name: 'popperOffsets', - enabled: true, - phase: 'read', - fn: popperOffsets, - data: {} - }; - - var unsetSides = { - top: 'auto', - right: 'auto', - bottom: 'auto', - left: 'auto' - }; // Round the offsets to the nearest suitable subpixel based on the DPR. - // Zooming can change the DPR, but it seems to report a value that will - // cleanly divide the values into the appropriate subpixels. - - function roundOffsetsByDPR(_ref) { - var x = _ref.x, - y = _ref.y; - var win = window; - var dpr = win.devicePixelRatio || 1; - return { - x: round(round(x * dpr) / dpr) || 0, - y: round(round(y * dpr) / dpr) || 0 - }; - } - - function mapToStyles(_ref2) { - var _Object$assign2; - - var popper = _ref2.popper, - popperRect = _ref2.popperRect, - placement = _ref2.placement, - offsets = _ref2.offsets, - position = _ref2.position, - gpuAcceleration = _ref2.gpuAcceleration, - adaptive = _ref2.adaptive, - roundOffsets = _ref2.roundOffsets; - - var _ref3 = roundOffsets === true ? roundOffsetsByDPR(offsets) : typeof roundOffsets === 'function' ? roundOffsets(offsets) : offsets, - _ref3$x = _ref3.x, - x = _ref3$x === void 0 ? 0 : _ref3$x, - _ref3$y = _ref3.y, - y = _ref3$y === void 0 ? 0 : _ref3$y; - - var hasX = offsets.hasOwnProperty('x'); - var hasY = offsets.hasOwnProperty('y'); - var sideX = left; - var sideY = top; - var win = window; - - if (adaptive) { - var offsetParent = getOffsetParent(popper); - var heightProp = 'clientHeight'; - var widthProp = 'clientWidth'; - - if (offsetParent === getWindow(popper)) { - offsetParent = getDocumentElement(popper); - - if (getComputedStyle(offsetParent).position !== 'static') { - heightProp = 'scrollHeight'; - widthProp = 'scrollWidth'; - } - } // $FlowFixMe[incompatible-cast]: force type refinement, we compare offsetParent with window above, but Flow doesn't detect it - - /*:: offsetParent = (offsetParent: Element); */ - - - if (placement === top) { - sideY = bottom; // $FlowFixMe[prop-missing] - - y -= offsetParent[heightProp] - popperRect.height; - y *= gpuAcceleration ? 1 : -1; - } - - if (placement === left) { - sideX = right; // $FlowFixMe[prop-missing] - - x -= offsetParent[widthProp] - popperRect.width; - x *= gpuAcceleration ? 1 : -1; - } - } - - var commonStyles = Object.assign({ - position: position - }, adaptive && unsetSides); - - if (gpuAcceleration) { - var _Object$assign; - - return Object.assign({}, commonStyles, (_Object$assign = {}, _Object$assign[sideY] = hasY ? '0' : '', _Object$assign[sideX] = hasX ? '0' : '', _Object$assign.transform = (win.devicePixelRatio || 1) < 2 ? "translate(" + x + "px, " + y + "px)" : "translate3d(" + x + "px, " + y + "px, 0)", _Object$assign)); - } - - return Object.assign({}, commonStyles, (_Object$assign2 = {}, _Object$assign2[sideY] = hasY ? y + "px" : '', _Object$assign2[sideX] = hasX ? x + "px" : '', _Object$assign2.transform = '', _Object$assign2)); - } - - function computeStyles(_ref4) { - var state = _ref4.state, - options = _ref4.options; - var _options$gpuAccelerat = options.gpuAcceleration, - gpuAcceleration = _options$gpuAccelerat === void 0 ? true : _options$gpuAccelerat, - _options$adaptive = options.adaptive, - adaptive = _options$adaptive === void 0 ? true : _options$adaptive, - _options$roundOffsets = options.roundOffsets, - roundOffsets = _options$roundOffsets === void 0 ? true : _options$roundOffsets; - - { - var transitionProperty = getComputedStyle(state.elements.popper).transitionProperty || ''; - - if (adaptive && ['transform', 'top', 'right', 'bottom', 'left'].some(function (property) { - return transitionProperty.indexOf(property) >= 0; - })) { - console.warn(['Popper: Detected CSS transitions on at least one of the following', 'CSS properties: "transform", "top", "right", "bottom", "left".', '\n\n', 'Disable the "computeStyles" modifier\'s `adaptive` option to allow', 'for smooth transitions, or remove these properties from the CSS', 'transition declaration on the popper element if only transitioning', 'opacity or background-color for example.', '\n\n', 'We recommend using the popper element as a wrapper around an inner', 'element that can have any CSS property transitioned for animations.'].join(' ')); - } - } - - var commonStyles = { - placement: getBasePlacement(state.placement), - popper: state.elements.popper, - popperRect: state.rects.popper, - gpuAcceleration: gpuAcceleration - }; - - if (state.modifiersData.popperOffsets != null) { - state.styles.popper = Object.assign({}, state.styles.popper, mapToStyles(Object.assign({}, commonStyles, { - offsets: state.modifiersData.popperOffsets, - position: state.options.strategy, - adaptive: adaptive, - roundOffsets: roundOffsets - }))); - } - - if (state.modifiersData.arrow != null) { - state.styles.arrow = Object.assign({}, state.styles.arrow, mapToStyles(Object.assign({}, commonStyles, { - offsets: state.modifiersData.arrow, - position: 'absolute', - adaptive: false, - roundOffsets: roundOffsets - }))); - } - - state.attributes.popper = Object.assign({}, state.attributes.popper, { - 'data-popper-placement': state.placement - }); - } // eslint-disable-next-line import/no-unused-modules - - - var computeStyles$1 = { - name: 'computeStyles', - enabled: true, - phase: 'beforeWrite', - fn: computeStyles, - data: {} - }; - - // and applies them to the HTMLElements such as popper and arrow - - function applyStyles(_ref) { - var state = _ref.state; - Object.keys(state.elements).forEach(function (name) { - var style = state.styles[name] || {}; - var attributes = state.attributes[name] || {}; - var element = state.elements[name]; // arrow is optional + virtual elements - - if (!isHTMLElement(element) || !getNodeName(element)) { - return; - } // Flow doesn't support to extend this property, but it's the most - // effective way to apply styles to an HTMLElement - // $FlowFixMe[cannot-write] - - - Object.assign(element.style, style); - Object.keys(attributes).forEach(function (name) { - var value = attributes[name]; - - if (value === false) { - element.removeAttribute(name); - } else { - element.setAttribute(name, value === true ? '' : value); - } - }); - }); - } - - function effect$1(_ref2) { - var state = _ref2.state; - var initialStyles = { - popper: { - position: state.options.strategy, - left: '0', - top: '0', - margin: '0' - }, - arrow: { - position: 'absolute' - }, - reference: {} - }; - Object.assign(state.elements.popper.style, initialStyles.popper); - state.styles = initialStyles; - - if (state.elements.arrow) { - Object.assign(state.elements.arrow.style, initialStyles.arrow); - } - - return function () { - Object.keys(state.elements).forEach(function (name) { - var element = state.elements[name]; - var attributes = state.attributes[name] || {}; - var styleProperties = Object.keys(state.styles.hasOwnProperty(name) ? state.styles[name] : initialStyles[name]); // Set all values to an empty string to unset them - - var style = styleProperties.reduce(function (style, property) { - style[property] = ''; - return style; - }, {}); // arrow is optional + virtual elements - - if (!isHTMLElement(element) || !getNodeName(element)) { - return; - } - - Object.assign(element.style, style); - Object.keys(attributes).forEach(function (attribute) { - element.removeAttribute(attribute); - }); - }); - }; - } // eslint-disable-next-line import/no-unused-modules - - - var applyStyles$1 = { - name: 'applyStyles', - enabled: true, - phase: 'write', - fn: applyStyles, - effect: effect$1, - requires: ['computeStyles'] - }; - - function distanceAndSkiddingToXY(placement, rects, offset) { - var basePlacement = getBasePlacement(placement); - var invertDistance = [left, top].indexOf(basePlacement) >= 0 ? -1 : 1; - - var _ref = typeof offset === 'function' ? offset(Object.assign({}, rects, { - placement: placement - })) : offset, - skidding = _ref[0], - distance = _ref[1]; - - skidding = skidding || 0; - distance = (distance || 0) * invertDistance; - return [left, right].indexOf(basePlacement) >= 0 ? { - x: distance, - y: skidding - } : { - x: skidding, - y: distance - }; - } - - function offset(_ref2) { - var state = _ref2.state, - options = _ref2.options, - name = _ref2.name; - var _options$offset = options.offset, - offset = _options$offset === void 0 ? [0, 0] : _options$offset; - var data = placements.reduce(function (acc, placement) { - acc[placement] = distanceAndSkiddingToXY(placement, state.rects, offset); - return acc; - }, {}); - var _data$state$placement = data[state.placement], - x = _data$state$placement.x, - y = _data$state$placement.y; - - if (state.modifiersData.popperOffsets != null) { - state.modifiersData.popperOffsets.x += x; - state.modifiersData.popperOffsets.y += y; - } - - state.modifiersData[name] = data; - } // eslint-disable-next-line import/no-unused-modules - - - var offset$1 = { - name: 'offset', - enabled: true, - phase: 'main', - requires: ['popperOffsets'], - fn: offset - }; - - var hash = { - left: 'right', - right: 'left', - bottom: 'top', - top: 'bottom' - }; - function getOppositePlacement(placement) { - return placement.replace(/left|right|bottom|top/g, function (matched) { - return hash[matched]; - }); - } - - var hash$1 = { - start: 'end', - end: 'start' - }; - function getOppositeVariationPlacement(placement) { - return placement.replace(/start|end/g, function (matched) { - return hash$1[matched]; - }); - } - - /*:: type OverflowsMap = { [ComputedPlacement]: number }; */ - - /*;; type OverflowsMap = { [key in ComputedPlacement]: number }; */ - function computeAutoPlacement(state, options) { - if (options === void 0) { - options = {}; - } - - var _options = options, - placement = _options.placement, - boundary = _options.boundary, - rootBoundary = _options.rootBoundary, - padding = _options.padding, - flipVariations = _options.flipVariations, - _options$allowedAutoP = _options.allowedAutoPlacements, - allowedAutoPlacements = _options$allowedAutoP === void 0 ? placements : _options$allowedAutoP; - var variation = getVariation(placement); - var placements$1 = variation ? flipVariations ? variationPlacements : variationPlacements.filter(function (placement) { - return getVariation(placement) === variation; - }) : basePlacements; - var allowedPlacements = placements$1.filter(function (placement) { - return allowedAutoPlacements.indexOf(placement) >= 0; - }); - - if (allowedPlacements.length === 0) { - allowedPlacements = placements$1; - - { - console.error(['Popper: The `allowedAutoPlacements` option did not allow any', 'placements. Ensure the `placement` option matches the variation', 'of the allowed placements.', 'For example, "auto" cannot be used to allow "bottom-start".', 'Use "auto-start" instead.'].join(' ')); - } - } // $FlowFixMe[incompatible-type]: Flow seems to have problems with two array unions... - - - var overflows = allowedPlacements.reduce(function (acc, placement) { - acc[placement] = detectOverflow(state, { - placement: placement, - boundary: boundary, - rootBoundary: rootBoundary, - padding: padding - })[getBasePlacement(placement)]; - return acc; - }, {}); - return Object.keys(overflows).sort(function (a, b) { - return overflows[a] - overflows[b]; - }); - } - - function getExpandedFallbackPlacements(placement) { - if (getBasePlacement(placement) === auto) { - return []; - } - - var oppositePlacement = getOppositePlacement(placement); - return [getOppositeVariationPlacement(placement), oppositePlacement, getOppositeVariationPlacement(oppositePlacement)]; - } - - function flip(_ref) { - var state = _ref.state, - options = _ref.options, - name = _ref.name; - - if (state.modifiersData[name]._skip) { - return; - } - - var _options$mainAxis = options.mainAxis, - checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, - _options$altAxis = options.altAxis, - checkAltAxis = _options$altAxis === void 0 ? true : _options$altAxis, - specifiedFallbackPlacements = options.fallbackPlacements, - padding = options.padding, - boundary = options.boundary, - rootBoundary = options.rootBoundary, - altBoundary = options.altBoundary, - _options$flipVariatio = options.flipVariations, - flipVariations = _options$flipVariatio === void 0 ? true : _options$flipVariatio, - allowedAutoPlacements = options.allowedAutoPlacements; - var preferredPlacement = state.options.placement; - var basePlacement = getBasePlacement(preferredPlacement); - var isBasePlacement = basePlacement === preferredPlacement; - var fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipVariations ? [getOppositePlacement(preferredPlacement)] : getExpandedFallbackPlacements(preferredPlacement)); - var placements = [preferredPlacement].concat(fallbackPlacements).reduce(function (acc, placement) { - return acc.concat(getBasePlacement(placement) === auto ? computeAutoPlacement(state, { - placement: placement, - boundary: boundary, - rootBoundary: rootBoundary, - padding: padding, - flipVariations: flipVariations, - allowedAutoPlacements: allowedAutoPlacements - }) : placement); - }, []); - var referenceRect = state.rects.reference; - var popperRect = state.rects.popper; - var checksMap = new Map(); - var makeFallbackChecks = true; - var firstFittingPlacement = placements[0]; - - for (var i = 0; i < placements.length; i++) { - var placement = placements[i]; - - var _basePlacement = getBasePlacement(placement); - - var isStartVariation = getVariation(placement) === start; - var isVertical = [top, bottom].indexOf(_basePlacement) >= 0; - var len = isVertical ? 'width' : 'height'; - var overflow = detectOverflow(state, { - placement: placement, - boundary: boundary, - rootBoundary: rootBoundary, - altBoundary: altBoundary, - padding: padding - }); - var mainVariationSide = isVertical ? isStartVariation ? right : left : isStartVariation ? bottom : top; - - if (referenceRect[len] > popperRect[len]) { - mainVariationSide = getOppositePlacement(mainVariationSide); - } - - var altVariationSide = getOppositePlacement(mainVariationSide); - var checks = []; - - if (checkMainAxis) { - checks.push(overflow[_basePlacement] <= 0); - } - - if (checkAltAxis) { - checks.push(overflow[mainVariationSide] <= 0, overflow[altVariationSide] <= 0); - } - - if (checks.every(function (check) { - return check; - })) { - firstFittingPlacement = placement; - makeFallbackChecks = false; - break; - } - - checksMap.set(placement, checks); - } - - if (makeFallbackChecks) { - // `2` may be desired in some cases – research later - var numberOfChecks = flipVariations ? 3 : 1; - - var _loop = function _loop(_i) { - var fittingPlacement = placements.find(function (placement) { - var checks = checksMap.get(placement); - - if (checks) { - return checks.slice(0, _i).every(function (check) { - return check; - }); - } - }); - - if (fittingPlacement) { - firstFittingPlacement = fittingPlacement; - return "break"; - } - }; - - for (var _i = numberOfChecks; _i > 0; _i--) { - var _ret = _loop(_i); - - if (_ret === "break") break; - } - } - - if (state.placement !== firstFittingPlacement) { - state.modifiersData[name]._skip = true; - state.placement = firstFittingPlacement; - state.reset = true; - } - } // eslint-disable-next-line import/no-unused-modules - - - var flip$1 = { - name: 'flip', - enabled: true, - phase: 'main', - fn: flip, - requiresIfExists: ['offset'], - data: { - _skip: false - } - }; - - function getAltAxis(axis) { - return axis === 'x' ? 'y' : 'x'; - } - - function within(min$1, value, max$1) { - return max(min$1, min(value, max$1)); - } - - function preventOverflow(_ref) { - var state = _ref.state, - options = _ref.options, - name = _ref.name; - var _options$mainAxis = options.mainAxis, - checkMainAxis = _options$mainAxis === void 0 ? true : _options$mainAxis, - _options$altAxis = options.altAxis, - checkAltAxis = _options$altAxis === void 0 ? false : _options$altAxis, - boundary = options.boundary, - rootBoundary = options.rootBoundary, - altBoundary = options.altBoundary, - padding = options.padding, - _options$tether = options.tether, - tether = _options$tether === void 0 ? true : _options$tether, - _options$tetherOffset = options.tetherOffset, - tetherOffset = _options$tetherOffset === void 0 ? 0 : _options$tetherOffset; - var overflow = detectOverflow(state, { - boundary: boundary, - rootBoundary: rootBoundary, - padding: padding, - altBoundary: altBoundary - }); - var basePlacement = getBasePlacement(state.placement); - var variation = getVariation(state.placement); - var isBasePlacement = !variation; - var mainAxis = getMainAxisFromPlacement(basePlacement); - var altAxis = getAltAxis(mainAxis); - var popperOffsets = state.modifiersData.popperOffsets; - var referenceRect = state.rects.reference; - var popperRect = state.rects.popper; - var tetherOffsetValue = typeof tetherOffset === 'function' ? tetherOffset(Object.assign({}, state.rects, { - placement: state.placement - })) : tetherOffset; - var data = { - x: 0, - y: 0 - }; - - if (!popperOffsets) { - return; - } - - if (checkMainAxis || checkAltAxis) { - var mainSide = mainAxis === 'y' ? top : left; - var altSide = mainAxis === 'y' ? bottom : right; - var len = mainAxis === 'y' ? 'height' : 'width'; - var offset = popperOffsets[mainAxis]; - var min$1 = popperOffsets[mainAxis] + overflow[mainSide]; - var max$1 = popperOffsets[mainAxis] - overflow[altSide]; - var additive = tether ? -popperRect[len] / 2 : 0; - var minLen = variation === start ? referenceRect[len] : popperRect[len]; - var maxLen = variation === start ? -popperRect[len] : -referenceRect[len]; // We need to include the arrow in the calculation so the arrow doesn't go - // outside the reference bounds - - var arrowElement = state.elements.arrow; - var arrowRect = tether && arrowElement ? getLayoutRect(arrowElement) : { - width: 0, - height: 0 - }; - var arrowPaddingObject = state.modifiersData['arrow#persistent'] ? state.modifiersData['arrow#persistent'].padding : getFreshSideObject(); - var arrowPaddingMin = arrowPaddingObject[mainSide]; - var arrowPaddingMax = arrowPaddingObject[altSide]; // If the reference length is smaller than the arrow length, we don't want - // to include its full size in the calculation. If the reference is small - // and near the edge of a boundary, the popper can overflow even if the - // reference is not overflowing as well (e.g. virtual elements with no - // width or height) - - var arrowLen = within(0, referenceRect[len], arrowRect[len]); - var minOffset = isBasePlacement ? referenceRect[len] / 2 - additive - arrowLen - arrowPaddingMin - tetherOffsetValue : minLen - arrowLen - arrowPaddingMin - tetherOffsetValue; - var maxOffset = isBasePlacement ? -referenceRect[len] / 2 + additive + arrowLen + arrowPaddingMax + tetherOffsetValue : maxLen + arrowLen + arrowPaddingMax + tetherOffsetValue; - var arrowOffsetParent = state.elements.arrow && getOffsetParent(state.elements.arrow); - var clientOffset = arrowOffsetParent ? mainAxis === 'y' ? arrowOffsetParent.clientTop || 0 : arrowOffsetParent.clientLeft || 0 : 0; - var offsetModifierValue = state.modifiersData.offset ? state.modifiersData.offset[state.placement][mainAxis] : 0; - var tetherMin = popperOffsets[mainAxis] + minOffset - offsetModifierValue - clientOffset; - var tetherMax = popperOffsets[mainAxis] + maxOffset - offsetModifierValue; - - if (checkMainAxis) { - var preventedOffset = within(tether ? min(min$1, tetherMin) : min$1, offset, tether ? max(max$1, tetherMax) : max$1); - popperOffsets[mainAxis] = preventedOffset; - data[mainAxis] = preventedOffset - offset; - } - - if (checkAltAxis) { - var _mainSide = mainAxis === 'x' ? top : left; - - var _altSide = mainAxis === 'x' ? bottom : right; - - var _offset = popperOffsets[altAxis]; - - var _min = _offset + overflow[_mainSide]; - - var _max = _offset - overflow[_altSide]; - - var _preventedOffset = within(tether ? min(_min, tetherMin) : _min, _offset, tether ? max(_max, tetherMax) : _max); - - popperOffsets[altAxis] = _preventedOffset; - data[altAxis] = _preventedOffset - _offset; - } - } - - state.modifiersData[name] = data; - } // eslint-disable-next-line import/no-unused-modules - - - var preventOverflow$1 = { - name: 'preventOverflow', - enabled: true, - phase: 'main', - fn: preventOverflow, - requiresIfExists: ['offset'] - }; - - var toPaddingObject = function toPaddingObject(padding, state) { - padding = typeof padding === 'function' ? padding(Object.assign({}, state.rects, { - placement: state.placement - })) : padding; - return mergePaddingObject(typeof padding !== 'number' ? padding : expandToHashMap(padding, basePlacements)); - }; - - function arrow(_ref) { - var _state$modifiersData$; - - var state = _ref.state, - name = _ref.name, - options = _ref.options; - var arrowElement = state.elements.arrow; - var popperOffsets = state.modifiersData.popperOffsets; - var basePlacement = getBasePlacement(state.placement); - var axis = getMainAxisFromPlacement(basePlacement); - var isVertical = [left, right].indexOf(basePlacement) >= 0; - var len = isVertical ? 'height' : 'width'; - - if (!arrowElement || !popperOffsets) { - return; - } - - var paddingObject = toPaddingObject(options.padding, state); - var arrowRect = getLayoutRect(arrowElement); - var minProp = axis === 'y' ? top : left; - var maxProp = axis === 'y' ? bottom : right; - var endDiff = state.rects.reference[len] + state.rects.reference[axis] - popperOffsets[axis] - state.rects.popper[len]; - var startDiff = popperOffsets[axis] - state.rects.reference[axis]; - var arrowOffsetParent = getOffsetParent(arrowElement); - var clientSize = arrowOffsetParent ? axis === 'y' ? arrowOffsetParent.clientHeight || 0 : arrowOffsetParent.clientWidth || 0 : 0; - var centerToReference = endDiff / 2 - startDiff / 2; // Make sure the arrow doesn't overflow the popper if the center point is - // outside of the popper bounds - - var min = paddingObject[minProp]; - var max = clientSize - arrowRect[len] - paddingObject[maxProp]; - var center = clientSize / 2 - arrowRect[len] / 2 + centerToReference; - var offset = within(min, center, max); // Prevents breaking syntax highlighting... - - var axisProp = axis; - state.modifiersData[name] = (_state$modifiersData$ = {}, _state$modifiersData$[axisProp] = offset, _state$modifiersData$.centerOffset = offset - center, _state$modifiersData$); - } - - function effect$2(_ref2) { - var state = _ref2.state, - options = _ref2.options; - var _options$element = options.element, - arrowElement = _options$element === void 0 ? '[data-popper-arrow]' : _options$element; - - if (arrowElement == null) { - return; - } // CSS selector - - - if (typeof arrowElement === 'string') { - arrowElement = state.elements.popper.querySelector(arrowElement); - - if (!arrowElement) { - return; - } - } - - { - if (!isHTMLElement(arrowElement)) { - console.error(['Popper: "arrow" element must be an HTMLElement (not an SVGElement).', 'To use an SVG arrow, wrap it in an HTMLElement that will be used as', 'the arrow.'].join(' ')); - } - } - - if (!contains(state.elements.popper, arrowElement)) { - { - console.error(['Popper: "arrow" modifier\'s `element` must be a child of the popper', 'element.'].join(' ')); - } - - return; - } - - state.elements.arrow = arrowElement; - } // eslint-disable-next-line import/no-unused-modules - - - var arrow$1 = { - name: 'arrow', - enabled: true, - phase: 'main', - fn: arrow, - effect: effect$2, - requires: ['popperOffsets'], - requiresIfExists: ['preventOverflow'] - }; - - function getSideOffsets(overflow, rect, preventedOffsets) { - if (preventedOffsets === void 0) { - preventedOffsets = { - x: 0, - y: 0 - }; - } - - return { - top: overflow.top - rect.height - preventedOffsets.y, - right: overflow.right - rect.width + preventedOffsets.x, - bottom: overflow.bottom - rect.height + preventedOffsets.y, - left: overflow.left - rect.width - preventedOffsets.x - }; - } - - function isAnySideFullyClipped(overflow) { - return [top, right, bottom, left].some(function (side) { - return overflow[side] >= 0; - }); - } - - function hide(_ref) { - var state = _ref.state, - name = _ref.name; - var referenceRect = state.rects.reference; - var popperRect = state.rects.popper; - var preventedOffsets = state.modifiersData.preventOverflow; - var referenceOverflow = detectOverflow(state, { - elementContext: 'reference' - }); - var popperAltOverflow = detectOverflow(state, { - altBoundary: true - }); - var referenceClippingOffsets = getSideOffsets(referenceOverflow, referenceRect); - var popperEscapeOffsets = getSideOffsets(popperAltOverflow, popperRect, preventedOffsets); - var isReferenceHidden = isAnySideFullyClipped(referenceClippingOffsets); - var hasPopperEscaped = isAnySideFullyClipped(popperEscapeOffsets); - state.modifiersData[name] = { - referenceClippingOffsets: referenceClippingOffsets, - popperEscapeOffsets: popperEscapeOffsets, - isReferenceHidden: isReferenceHidden, - hasPopperEscaped: hasPopperEscaped - }; - state.attributes.popper = Object.assign({}, state.attributes.popper, { - 'data-popper-reference-hidden': isReferenceHidden, - 'data-popper-escaped': hasPopperEscaped - }); - } // eslint-disable-next-line import/no-unused-modules - - - var hide$1 = { - name: 'hide', - enabled: true, - phase: 'main', - requiresIfExists: ['preventOverflow'], - fn: hide - }; - - var defaultModifiers = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1]; - var createPopper = /*#__PURE__*/popperGenerator({ - defaultModifiers: defaultModifiers - }); // eslint-disable-next-line import/no-unused-modules - - var defaultModifiers$1 = [eventListeners, popperOffsets$1, computeStyles$1, applyStyles$1, offset$1, flip$1, preventOverflow$1, arrow$1, hide$1]; - var createPopper$1 = /*#__PURE__*/popperGenerator({ - defaultModifiers: defaultModifiers$1 - }); // eslint-disable-next-line import/no-unused-modules - - exports.applyStyles = applyStyles$1; - exports.arrow = arrow$1; - exports.computeStyles = computeStyles$1; - exports.createPopper = createPopper$1; - exports.createPopperLite = createPopper; - exports.defaultModifiers = defaultModifiers$1; - exports.detectOverflow = detectOverflow; - exports.eventListeners = eventListeners; - exports.flip = flip$1; - exports.hide = hide$1; - exports.offset = offset$1; - exports.popperGenerator = popperGenerator; - exports.popperOffsets = popperOffsets$1; - exports.preventOverflow = preventOverflow$1; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=popper.js.map - - -; - -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var __spreadArray = (this && this.__spreadArray) || function (to, from) { - for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) - to[j] = from[i]; - return to; -}; -var Stacks; -(function (Stacks) { - var StacksApplication = (function (_super) { - __extends(StacksApplication, _super); - function StacksApplication() { - return _super !== null && _super.apply(this, arguments) || this; - } - StacksApplication.prototype.load = function (head) { - var rest = []; - for (var _i = 1; _i < arguments.length; _i++) { - rest[_i - 1] = arguments[_i]; - } - var definitions = Array.isArray(head) ? head : __spreadArray([head], rest); - for (var _a = 0, definitions_1 = definitions; _a < definitions_1.length; _a++) { - var definition = definitions_1[_a]; - var hasPrefix = /^s-/.test(definition.identifier); - if (Stacks._initializing && !hasPrefix) { - throw "Stacks-created Stimulus controller names must start with \"s-\"."; - } - if (!Stacks._initializing && hasPrefix) { - throw "The \"s-\" prefix on Stimulus controller names is reserved for Stacks-created controllers."; - } - } - _super.prototype.load.call(this, definitions); - }; - StacksApplication.start = function (element, schema) { - var application = new StacksApplication(element, schema); - application.start(); - return application; - }; - return StacksApplication; - }(Stimulus.Application)); - Stacks.application = StacksApplication.start(); - Stacks._initializing = true; - var StacksController = (function (_super) { - __extends(StacksController, _super); - function StacksController() { - return _super !== null && _super.apply(this, arguments) || this; - } - StacksController.prototype.getElementData = function (element, key) { - return element.getAttribute("data-" + this.identifier + "-" + key); - }; - ; - StacksController.prototype.setElementData = function (element, key, value) { - element.setAttribute("data-" + this.identifier + "-" + key, value); - }; - ; - StacksController.prototype.removeElementData = function (element, key) { - element.removeAttribute("data-" + this.identifier + "-" + key); - }; - ; - StacksController.prototype.triggerEvent = function (eventName, detail, optionalElement) { - var namespacedName = this.identifier + ":" + eventName; - var event; - try { - event = new CustomEvent(namespacedName, { bubbles: true, cancelable: true, detail: detail }); - } - catch (ex) { - event = document.createEvent("CustomEvent"); - event.initCustomEvent(namespacedName, true, true, detail); - } - (optionalElement || this.element).dispatchEvent(event); - return event; - }; - ; - return StacksController; - }(Stimulus.Controller)); - Stacks.StacksController = StacksController; - function createController(controllerDefinition) { - var _a; - var Controller = controllerDefinition.hasOwnProperty("targets") - ? (_a = (function (_super) { - __extends(Controller, _super); - function Controller() { - return _super !== null && _super.apply(this, arguments) || this; - } - return Controller; - }(StacksController)), - _a.targets = controllerDefinition.targets, - _a) : (function (_super) { - __extends(Controller, _super); - function Controller() { - return _super !== null && _super.apply(this, arguments) || this; - } - return Controller; - }(StacksController)); - for (var prop in controllerDefinition) { - if (prop !== "targets" && controllerDefinition.hasOwnProperty(prop)) { - Object.defineProperty(Controller.prototype, prop, Object.getOwnPropertyDescriptor(controllerDefinition, prop)); - } - } - return Controller; - } - Stacks.createController = createController; - function addController(name, controller) { - Stacks.application.register(name, createController(controller)); - } - Stacks.addController = addController; -})(Stacks || (Stacks = {})); -//# sourceMappingURL=stacks.js.map - -; - -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -(function () { - var RADIO_OFF_EVENT = "s-expandable-control:radio-off"; - function globalChangeListener(e) { - var target = e.target; - if (!(target instanceof HTMLInputElement) || target.nodeName !== "INPUT" || target.type !== "radio") { - return; - } - document.querySelectorAll('input[type="radio"][name="' + target.name + '"]') - .forEach(function (other) { - if (other === e.target) { - return; - } - var customEvent; - try { - customEvent = new Event(RADIO_OFF_EVENT); - } - catch (ex) { - customEvent = document.createEvent("Event"); - customEvent.initEvent(RADIO_OFF_EVENT, true, true); - } - other.dispatchEvent(customEvent); - }); - } - var refCount = 0; - function globalChangeListenerRequired(required) { - if (required) { - refCount++; - if (refCount === 1) { - document.body.addEventListener("change", globalChangeListener); - } - } - else { - refCount--; - if (refCount === 0) { - document.body.removeEventListener("change", globalChangeListener); - } - } - } - Stacks.application.register("s-expandable-control", (function (_super) { - __extends(class_1, _super); - function class_1() { - return _super !== null && _super.apply(this, arguments) || this; - } - class_1.prototype.initialize = function () { - if (this.element.nodeName === "INPUT" && ["radio", "checkbox"].indexOf(this.element.type) >= 0) { - this.isCollapsed = this._isCollapsedForCheckable; - this.events = ["change", RADIO_OFF_EVENT]; - this.isCheckable = true; - this.isRadio = this.element.type === "radio"; - } - else { - this.isCollapsed = this._isCollapsedForClickable; - this.events = ["click", "keydown"]; - } - this.listener = this.listener.bind(this); - }; - ; - class_1.prototype._isCollapsedForClickable = function () { - var cc = this.controlledCollapsible; - return cc ? !cc.classList.contains("is-expanded") : this.element.getAttribute("aria-expanded") === "false"; - }; - ; - class_1.prototype._isCollapsedForCheckable = function () { - return !this.element.checked; - }; - ; - Object.defineProperty(class_1.prototype, "controlledCollapsible", { - get: function () { - var attr = this.element.getAttribute("aria-controls"); - if (!attr) { - throw "couldn't find controls"; - } - var result = document.getElementById(attr); - if (!result) { - throw "couldn't find controls"; - } - return result; - }, - enumerable: false, - configurable: true - }); - ; - class_1.prototype._dispatchShowHideEvent = function (isShow) { - this.triggerEvent(isShow ? "show" : "hide"); - }; - ; - class_1.prototype._toggleClass = function (doAdd) { - if (!this.data.has("toggle-class")) { - return; - } - var cl = this.element.classList; - var toggleClass = this.data.get("toggle-class"); - if (!toggleClass) { - throw "couldn't find toggle class"; - } - toggleClass.split(/\s+/).forEach(function (cls) { - cl.toggle(cls, !!doAdd); - }); - }; - ; - class_1.prototype.listener = function (e) { - var newCollapsed; - if (this.isCheckable) { - newCollapsed = !this.element.checked; - } - else { - if (e.type == "keydown" && (e instanceof KeyboardEvent && e.keyCode != 13 && e.keyCode != 32)) { - return; - } - if (e.target !== e.currentTarget && ["A", "BUTTON"].indexOf(e.target.nodeName) >= 0) { - return; - } - newCollapsed = this.element.getAttribute("aria-expanded") === "true"; - e.preventDefault(); - if (e.type === "click") { - this.element.blur(); - } - } - this.element.setAttribute("aria-expanded", newCollapsed ? "false" : "true"); - this.controlledCollapsible.classList.toggle("is-expanded", !newCollapsed); - this._dispatchShowHideEvent(!newCollapsed); - this._toggleClass(!newCollapsed); - }; - ; - class_1.prototype.connect = function () { - var _this = this; - this.events.forEach(function (e) { - _this.element.addEventListener(e, _this.listener); - }, this); - if (this.isRadio) { - globalChangeListenerRequired(true); - } - this.element.setAttribute("aria-expanded", this.isCollapsed() ? "false" : "true"); - if (this.isCheckable) { - var cc = this.controlledCollapsible; - if (cc) { - var expected = !this.isCollapsed(); - var actual = cc.classList.contains("is-expanded"); - if (expected !== actual) { - cc.classList.toggle("is-expanded", expected); - this._dispatchShowHideEvent(expected); - this._toggleClass(expected); - } - } - } - }; - ; - class_1.prototype.disconnect = function () { - var _this = this; - this.events.forEach(function (e) { - _this.element.removeEventListener(e, _this.listener); - }, this); - if (this.isRadio) { - globalChangeListenerRequired(false); - } - }; - ; - return class_1; - }(Stacks.StacksController))); -})(); -//# sourceMappingURL=s-expandable-control.js.map - -; - -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var Stacks; -(function (Stacks) { - var ModalController = (function (_super) { - __extends(ModalController, _super); - function ModalController() { - return _super !== null && _super.apply(this, arguments) || this; - } - ModalController.prototype.connect = function () { - this.validate(); - }; - ModalController.prototype.disconnect = function () { - this.unbindDocumentEvents(); - }; - ; - ModalController.prototype.toggle = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - this._toggle(undefined, dispatcher); - }; - ModalController.prototype.show = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - this._toggle(true, dispatcher); - }; - ModalController.prototype.hide = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - this._toggle(false, dispatcher); - }; - ModalController.prototype.validate = function () { - var returnElementSelector = this.data.get("return-element"); - if (returnElementSelector) { - this.returnElement = document.querySelector(returnElementSelector); - if (!this.returnElement) { - throw "Unable to find element by return-element selector: " + returnElementSelector; - } - } - }; - ModalController.prototype._toggle = function (show, dispatcher) { - var _this = this; - if (dispatcher === void 0) { dispatcher = null; } - var toShow = show; - var isVisible = this.modalTarget.getAttribute("aria-hidden") === "false"; - if (typeof toShow === "undefined") { - toShow = !isVisible; - } - if ((toShow && isVisible) || (!toShow && !isVisible)) { - return; - } - var dispatchingElement = this.getDispatcher(dispatcher); - var triggeredEvent = this.triggerEvent(toShow ? "show" : "hide", { - returnElement: this.returnElement, - dispatcher: this.getDispatcher(dispatchingElement) - }); - if (triggeredEvent.defaultPrevented) { - return; - } - this.returnElement = triggeredEvent.detail.returnElement; - this.modalTarget.setAttribute("aria-hidden", toShow ? "false" : "true"); - if (toShow) { - this.bindDocumentEvents(); - } - else { - this.unbindDocumentEvents(); - this.focusReturnElement(); - this.removeModalOnHide(); - } - var supportsTransitionEnd = this.modalTarget.ontransitionend !== undefined; - if (supportsTransitionEnd) { - this.modalTarget.addEventListener("transitionend", function () { - _this.triggerEvent(toShow ? "shown" : "hidden", { - dispatcher: dispatchingElement - }); - }, { once: true }); - } - else { - this.triggerEvent(toShow ? "shown" : "hidden", { - dispatcher: dispatchingElement - }); - } - }; - ModalController.prototype.focusReturnElement = function () { - var _this = this; - if (!this.returnElement) { - return; - } - this.modalTarget.addEventListener("s-modal:hidden", function () { - if (_this.returnElement && document.body.contains(_this.returnElement)) { - _this.returnElement.focus(); - } - }, { once: true }); - }; - ModalController.prototype.removeModalOnHide = function () { - var _this = this; - if (this.data.get("remove-when-hidden") !== "true") { - return; - } - this.modalTarget.addEventListener("s-modal:hidden", function () { - _this.element.remove(); - }, { once: true }); - }; - ModalController.prototype.handleFocusableElements = function () { - var _this = this; - var allTabbables = Array.from(this.modalTarget.querySelectorAll("[href], input, select, textarea, button, [tabindex]")) - .filter(function (el) { return el.matches(":not([disabled]):not([tabindex='-1'])"); }); - if (!allTabbables.length) { - return; - } - var initialFocus = allTabbables[0]; - if (this.hasInitialFocusTarget) { - initialFocus = this.initialFocusTarget; - } - this.modalTarget.addEventListener("s-modal:shown", function () { - if (initialFocus && document.body.contains(initialFocus)) { - initialFocus.focus(); - } - }, { once: true }); - var firstTabbable = allTabbables[0]; - var lastTabbable = allTabbables[allTabbables.length - 1]; - this._boundTabTrap = this._boundTabTrap || (function (e) { - if (!_this.modalTarget.contains(e.target)) { - e.preventDefault(); - firstTabbable.focus(); - } - if (e.target == firstTabbable && e.keyCode === 9 && e.shiftKey) { - e.preventDefault(); - lastTabbable.focus(); - } - if (e.target == lastTabbable && e.keyCode === 9 && !e.shiftKey) { - e.preventDefault(); - firstTabbable.focus(); - } - }); - document.addEventListener("keydown", this._boundTabTrap); - return initialFocus; - }; - ModalController.prototype.bindDocumentEvents = function () { - this._boundClickFn = this._boundClickFn || this.hideOnOutsideClick.bind(this); - this._boundKeypressFn = this._boundKeypressFn || this.hideOnEscapePress.bind(this); - document.addEventListener("mousedown", this._boundClickFn); - document.addEventListener("keyup", this._boundKeypressFn); - this.handleFocusableElements(); - }; - ModalController.prototype.unbindDocumentEvents = function () { - document.removeEventListener("mousedown", this._boundClickFn); - document.removeEventListener("keyup", this._boundKeypressFn); - document.removeEventListener("keydown", this._boundTabTrap); - }; - ModalController.prototype.hideOnOutsideClick = function (e) { - var target = e.target; - if (!this.modalTarget.querySelector(".s-modal--dialog").contains(target) && document.body.contains(target)) { - this._toggle(false, e); - } - }; - ModalController.prototype.hideOnEscapePress = function (e) { - if (e.which !== 27 || this.modalTarget.getAttribute("aria-hidden") === "true") { - return; - } - this._toggle(false, e); - }; - ModalController.prototype.getDispatcher = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - if (dispatcher instanceof Event) { - return dispatcher.target; - } - else if (dispatcher instanceof Element) { - return dispatcher; - } - else { - return this.element; - } - }; - ModalController.targets = ["modal", "initialFocus"]; - return ModalController; - }(Stacks.StacksController)); - Stacks.ModalController = ModalController; - function showModal(element) { - toggleModal(element, true); - } - Stacks.showModal = showModal; - function hideModal(element) { - toggleModal(element, false); - } - Stacks.hideModal = hideModal; - function toggleModal(element, show) { - var controller = Stacks.application.getControllerForElementAndIdentifier(element, "s-modal"); - if (!controller) { - throw "Unable to get s-modal controller from element"; - } - show ? controller.show() : controller.hide(); - } -})(Stacks || (Stacks = {})); -Stacks.application.register("s-modal", Stacks.ModalController); -//# sourceMappingURL=s-modal.js.map - -; - -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var Stacks; -(function (Stacks) { - var TabListController = (function (_super) { - __extends(TabListController, _super); - function TabListController() { - return _super !== null && _super.apply(this, arguments) || this; - } - TabListController.prototype.connect = function () { - _super.prototype.connect.call(this); - this.boundSelectTab = this.selectTab.bind(this); - this.boundHandleKeydown = this.handleKeydown.bind(this); - for (var _i = 0, _a = this.tabTargets; _i < _a.length; _i++) { - var tab = _a[_i]; - tab.addEventListener("click", this.boundSelectTab); - tab.addEventListener("keydown", this.boundHandleKeydown); - } - }; - TabListController.prototype.disconnect = function () { - _super.prototype.disconnect.call(this); - for (var _i = 0, _a = this.tabTargets; _i < _a.length; _i++) { - var tab = _a[_i]; - tab.removeEventListener("click", this.boundSelectTab); - tab.removeEventListener("keydown", this.boundHandleKeydown); - } - }; - Object.defineProperty(TabListController.prototype, "tabTargets", { - get: function () { - return Array.from(this.element.querySelectorAll("[role=tab]")); - }, - enumerable: false, - configurable: true - }); - TabListController.prototype.selectTab = function (event) { - this.switchToTab(event.currentTarget); - }; - TabListController.prototype.handleKeydown = function (event) { - var _a; - var tabElement = event.currentTarget; - var tabs = this.tabTargets; - var tabIndex = tabs.indexOf(tabElement); - if (event.key === "ArrowRight") { - tabIndex++; - } - else if (event.key === "ArrowLeft") { - tabIndex--; - } - else { - return; - } - if (tabIndex < 0) { - tabIndex = tabs.length - 1; - } - if (tabIndex >= tabs.length) { - tabIndex = 0; - } - tabElement = tabs[tabIndex]; - this.switchToTab(tabElement); - (_a = this.selectedTab) === null || _a === void 0 ? void 0 : _a.focus(); - }; - TabListController.prototype.switchToTab = function (newTab) { - var oldTab = this.selectedTab; - if (oldTab === newTab) { - return; - } - if (this.triggerEvent("select", { oldTab: oldTab, newTab: newTab }).defaultPrevented) { - return; - } - this.selectedTab = newTab; - this.triggerEvent("selected", { oldTab: oldTab, newTab: newTab }); - }; - Object.defineProperty(TabListController.prototype, "selectedTab", { - get: function () { - return this.tabTargets.find(function (e) { return e.getAttribute("aria-selected") === "true"; }) || null; - }, - set: function (selectedTab) { - for (var _i = 0, _a = this.tabTargets; _i < _a.length; _i++) { - var tab = _a[_i]; - var panelId = tab.getAttribute('aria-controls'); - var panel = panelId ? document.getElementById(panelId) : null; - if (tab === selectedTab) { - tab.classList.add('is-selected'); - tab.setAttribute('aria-selected', 'true'); - tab.removeAttribute('tabindex'); - panel === null || panel === void 0 ? void 0 : panel.classList.remove('d-none'); - } - else { - tab.classList.remove('is-selected'); - tab.setAttribute('aria-selected', 'false'); - tab.setAttribute('tabindex', '-1'); - panel === null || panel === void 0 ? void 0 : panel.classList.add('d-none'); - } - } - }, - enumerable: false, - configurable: true - }); - return TabListController; - }(Stacks.StacksController)); - Stacks.TabListController = TabListController; -})(Stacks || (Stacks = {})); -Stacks.application.register("s-navigation-tablist", Stacks.TabListController); -//# sourceMappingURL=s-navigation-tablist.js.map - -; - -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var Stacks; -(function (Stacks) { - var BasePopoverController = (function (_super) { - __extends(BasePopoverController, _super); - function BasePopoverController() { - return _super !== null && _super.apply(this, arguments) || this; - } - Object.defineProperty(BasePopoverController.prototype, "isVisible", { - get: function () { - var popoverElement = this.popoverElement; - return popoverElement ? popoverElement.classList.contains("is-visible") : false; - }, - enumerable: false, - configurable: true - }); - BasePopoverController.prototype.connect = function () { - _super.prototype.connect.call(this); - this.validate(); - if (this.isVisible) { - this.initializePopper(); - } - }; - BasePopoverController.prototype.disconnect = function () { - this.hide(); - if (this.popper) { - this.popper.destroy(); - this.popper = null; - } - _super.prototype.disconnect.call(this); - }; - BasePopoverController.prototype.toggle = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - this.isVisible ? this.hide(dispatcher) : this.show(dispatcher); - }; - BasePopoverController.prototype.show = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - if (this.isVisible) { - return; - } - var dispatcherElement = this.getDispatcher(dispatcher); - if (this.triggerEvent("show", { - dispatcher: dispatcherElement - }).defaultPrevented) { - return; - } - if (!this.popper) { - this.initializePopper(); - } - this.popoverElement.classList.add("is-visible"); - this.scheduleUpdate(); - this.shown(dispatcherElement); - }; - BasePopoverController.prototype.hide = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - if (!this.isVisible) { - return; - } - var dispatcherElement = this.getDispatcher(dispatcher); - if (this.triggerEvent("hide", { - dispatcher: dispatcherElement - }).defaultPrevented) { - return; - } - this.popoverElement.classList.remove("is-visible"); - if (this.popper) { - this.popper.destroy(); - this.popper = null; - } - this.hidden(dispatcherElement); - }; - BasePopoverController.prototype.shown = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - this.bindDocumentEvents(); - this.triggerEvent("shown", { - dispatcher: dispatcher - }); - }; - BasePopoverController.prototype.hidden = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - this.unbindDocumentEvents(); - this.triggerEvent("hidden", { - dispatcher: dispatcher - }); - }; - BasePopoverController.prototype.generatePopover = function () { - return null; - }; - BasePopoverController.prototype.initializePopper = function () { - this.popper = Popper.createPopper(this.referenceElement, this.popoverElement, { - placement: this.data.get("placement") || "bottom", - modifiers: [ - { - name: "offset", - options: { - offset: [0, 10], - } - }, - { - name: "arrow", - options: { - element: ".s-popover--arrow" - }, - }, - ] - }); - }; - BasePopoverController.prototype.validate = function () { - var referenceSelector = this.data.get("reference-selector"); - this.referenceElement = this.element; - if (referenceSelector) { - this.referenceElement = this.element.querySelector(referenceSelector); - if (!this.referenceElement) { - throw "Unable to find element by reference selector: " + referenceSelector; - } - } - var popoverId = this.referenceElement.getAttribute(this.popoverSelectorAttribute); - var popoverElement = null; - if (popoverId) { - popoverElement = document.getElementById(popoverId); - if (!popoverElement) { - throw "[" + this.popoverSelectorAttribute + "=\"{POPOVER_ID}\"] required"; - } - } - else { - popoverElement = this.generatePopover(); - } - if (!popoverElement) { - throw "unable to find or generate popover element"; - } - this.popoverElement = popoverElement; - }; - BasePopoverController.prototype.getDispatcher = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - if (dispatcher instanceof Event) { - return dispatcher.target; - } - else if (dispatcher instanceof Element) { - return dispatcher; - } - else { - return this.element; - } - }; - BasePopoverController.prototype.scheduleUpdate = function () { - if (this.popper && this.isVisible) { - this.popper.update(); - } - }; - return BasePopoverController; - }(Stacks.StacksController)); - Stacks.BasePopoverController = BasePopoverController; - var PopoverController = (function (_super) { - __extends(PopoverController, _super); - function PopoverController() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.popoverSelectorAttribute = "aria-controls"; - return _this; - } - PopoverController.prototype.shown = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - this.toggleOptionalClasses(true); - _super.prototype.shown.call(this, dispatcher); - }; - PopoverController.prototype.hidden = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - this.toggleOptionalClasses(false); - _super.prototype.hidden.call(this, dispatcher); - }; - PopoverController.prototype.bindDocumentEvents = function () { - this.boundHideOnOutsideClick = this.boundHideOnOutsideClick || this.hideOnOutsideClick.bind(this); - this.boundHideOnEscapePress = this.boundHideOnEscapePress || this.hideOnEscapePress.bind(this); - document.addEventListener("mousedown", this.boundHideOnOutsideClick); - document.addEventListener("keyup", this.boundHideOnEscapePress); - }; - PopoverController.prototype.unbindDocumentEvents = function () { - document.removeEventListener("mousedown", this.boundHideOnOutsideClick); - document.removeEventListener("keyup", this.boundHideOnEscapePress); - }; - PopoverController.prototype.hideOnOutsideClick = function (e) { - var target = e.target; - if (!this.referenceElement.contains(target) && !this.popoverElement.contains(target) && document.body.contains(target)) { - this.hide(e); - } - }; - ; - PopoverController.prototype.hideOnEscapePress = function (e) { - if (e.which !== 27 || !this.isVisible) { - return; - } - if (this.popoverElement.contains(e.target)) { - this.referenceElement.focus(); - } - this.hide(e); - }; - ; - PopoverController.prototype.toggleOptionalClasses = function (show) { - if (!this.data.has("toggle-class")) { - return; - } - var cl = this.referenceElement.classList; - this.data.get("toggle-class").split(/\s+/).forEach(function (cls) { - cl.toggle(cls, show); - }); - }; - PopoverController.targets = []; - return PopoverController; - }(BasePopoverController)); - Stacks.PopoverController = PopoverController; -})(Stacks || (Stacks = {})); -Stacks.application.register("s-popover", Stacks.PopoverController); -//# sourceMappingURL=s-popover.js.map - -; - -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -(function () { - var _a; - Stacks.application.register("s-table", (_a = (function (_super) { - __extends(class_1, _super); - function class_1() { - return _super !== null && _super.apply(this, arguments) || this; - } - class_1.prototype.setCurrentSort = function (headElem, direction) { - if (["asc", "desc", "none"].indexOf(direction) < 0) { - throw "direction must be one of asc, desc, or none"; - } - var controller = this; - this.columnTargets.forEach(function (target) { - var isCurrrent = target === headElem; - target.classList.toggle("is-sorted", isCurrrent && direction !== "none"); - target.querySelectorAll(".js-sorting-indicator").forEach(function (icon) { - var visible = isCurrrent ? direction : "none"; - icon.classList.toggle("d-none", !icon.classList.contains("js-sorting-indicator-" + visible)); - }); - if (!isCurrrent || direction === "none") { - controller.removeElementData(target, "sort-direction"); - } - else { - controller.setElementData(target, "sort-direction", direction); - } - }); - }; - ; - class_1.prototype.sort = function (evt) { - var controller = this; - var colHead = evt.currentTarget; - if (!(colHead instanceof HTMLTableCellElement)) { - throw "invalid event target"; - } - var table = this.element; - var tbody = table.tBodies[0]; - var colno = getCellSlot(colHead); - if (colno < 0) { - return; - } - var slotIndex = buildIndex(tbody); - var direction = this.getElementData(colHead, "sort-direction") === "asc" ? -1 : 1; - var rows = Array.from(table.tBodies[0].rows); - var anyNonInt = false; - var data = []; - var firstBottomRow; - rows.forEach(function (row, index) { - var force = controller.getElementData(row, "sort-to"); - if (force === "top") { - return; - } - else if (force === "bottom") { - if (!firstBottomRow) { - firstBottomRow = row; - } - return; - } - var cell = slotIndex[index][colno]; - if (!cell) { - data.push(["", index]); - return; - } - var explicit = controller.getElementData(cell, "sort-val"); - var d = typeof explicit === "string" ? explicit : cell.textContent.trim(); - if ((d !== "") && (parseInt(d, 10) + "" !== d)) { - anyNonInt = true; - } - data.push([d, index]); - }); - if (!anyNonInt) { - data.forEach(function (tuple) { - tuple[0] = tuple[0] === "" ? Number.MIN_VALUE : parseInt(tuple[0], 10); - }); - } - data.sort(function (a, b) { - if (a[0] > b[0]) { - return 1 * direction; - } - else if (a[0] < b[0]) { - return -1 * direction; - } - else { - return a[1] > b[1] ? 1 : -1; - } - }); - data.forEach(function (tup) { - var row = rows[tup[1]]; - row.parentElement.removeChild(row); - if (firstBottomRow) { - tbody.insertBefore(row, firstBottomRow); - } - else { - tbody.appendChild(row); - } - }); - this.setCurrentSort(colHead, direction === 1 ? "asc" : "desc"); - }; - return class_1; - }(Stacks.StacksController)), - _a.targets = ["column"], - _a)); - function buildIndex(section) { - var result = buildIndexOrGetCellSlot(section); - if (!(result instanceof Array)) { - throw "shouldn't happen"; - } - return result; - } - function getCellSlot(cell) { - if (!(cell.parentElement && cell.parentElement.parentElement instanceof HTMLTableSectionElement)) { - throw "invalid table"; - } - var result = buildIndexOrGetCellSlot(cell.parentElement.parentElement, cell); - if (typeof result !== "number") { - throw "shouldn't happen"; - } - return result; - } - function buildIndexOrGetCellSlot(section, findCell) { - var index = []; - var curRow = section.children[0]; - var growing = []; - var growingRowsLeft = []; - while (curRow || growingRowsLeft.some(function (e) { return e !== 0; })) { - var curIndexRow = []; - index.push(curIndexRow); - var curSlot = 0; - if (curRow) { - for (var curCellInd = 0; curCellInd < curRow.children.length; curCellInd++) { - while (growingRowsLeft[curSlot]) { - growingRowsLeft[curSlot]--; - curIndexRow[curSlot] = growing[curSlot]; - curSlot++; - } - var cell = curRow.children[curCellInd]; - if (!(cell instanceof HTMLTableCellElement)) { - throw "invalid table"; - } - if (getComputedStyle(cell).display === "none") { - continue; - } - if (cell === findCell) { - return curSlot; - } - var nextFreeSlot = curSlot + cell.colSpan; - for (; curSlot < nextFreeSlot; curSlot++) { - growingRowsLeft[curSlot] = cell.rowSpan - 1; - growing[curSlot] = cell; - curIndexRow[curSlot] = cell; - } - } - } - while (curSlot < growing.length) { - if (growingRowsLeft[curSlot]) { - growingRowsLeft[curSlot]--; - curIndexRow[curSlot] = growing[curSlot]; - } - curSlot++; - } - if (curRow) { - curRow = curRow.nextElementSibling; - } - } - return findCell ? -1 : index; - } -})(); -//# sourceMappingURL=s-table.js.map - -; - -"use strict"; -var __extends = (this && this.__extends) || (function () { - var extendStatics = function (d, b) { - extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; - return extendStatics(d, b); - }; - return function (d, b) { - if (typeof b !== "function" && b !== null) - throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; -})(); -var Stacks; -(function (Stacks) { - var TooltipController = (function (_super) { - __extends(TooltipController, _super); - function TooltipController() { - var _this = _super !== null && _super.apply(this, arguments) || this; - _this.popoverSelectorAttribute = "aria-describedby"; - return _this; - } - TooltipController.prototype.connect = function () { - _super.prototype.connect.call(this); - if (window.matchMedia("(hover: hover)").matches) { - this.bindMouseEvents(); - } - }; - TooltipController.prototype.disconnect = function () { - this.unbindMouseEvents(); - _super.prototype.disconnect.call(this); - }; - TooltipController.prototype.show = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - var controller = Stacks.application.getControllerForElementAndIdentifier(this.element, "s-popover"); - if (controller && controller.isVisible) { - return; - } - _super.prototype.show.call(this, dispatcher); - }; - TooltipController.prototype.scheduleShow = function (dispatcher) { - var _this = this; - if (dispatcher === void 0) { dispatcher = null; } - window.clearTimeout(this.activeTimeout); - this.activeTimeout = window.setTimeout(function () { return _this.show(dispatcher); }, 300); - }; - TooltipController.prototype.hide = function (dispatcher) { - if (dispatcher === void 0) { dispatcher = null; } - window.clearTimeout(this.activeTimeout); - this.activeTimeout = null; - _super.prototype.hide.call(this, dispatcher); - }; - TooltipController.prototype.applyTitleAttributes = function () { - var content; - var htmlTitle = this.data.get("html-title"); - if (htmlTitle) { - content = document.createRange().createContextualFragment(htmlTitle); - } - else { - var plainTitle = this.element.getAttribute("title"); - if (plainTitle) { - content = document.createTextNode(plainTitle); - } - else { - return null; - } - } - this.data.delete("html-title"); - this.element.removeAttribute("title"); - var popoverId = this.element.getAttribute("aria-describedby"); - if (!popoverId) { - popoverId = TooltipController.generateId(); - this.element.setAttribute("aria-describedby", popoverId); - } - var popover = document.getElementById(popoverId); - if (!popover) { - popover = document.createElement("div"); - popover.id = popoverId; - popover.className = "s-popover s-popover__tooltip pe-none"; - popover.setAttribute("aria-hidden", "true"); - popover.setAttribute("role", "tooltip"); - var parentNode = this.element.parentNode; - if (parentNode) { - parentNode.insertBefore(popover, this.element.nextSibling); - } - else { - document.body.appendChild(popover); - } - } - var arrow = popover.querySelector(".s-popover--arrow"); - popover.innerHTML = ""; - popover.appendChild(content); - if (arrow) { - popover.appendChild(arrow); - } - else { - popover.insertAdjacentHTML("beforeend", "
"); - } - this.scheduleUpdate(); - return popover; - }; - TooltipController.prototype.bindDocumentEvents = function () { - this.boundHideIfWithin = this.boundHideIfWithin || this.hideIfWithin.bind(this); - document.addEventListener("s-popover:shown", this.boundHideIfWithin); - }; - TooltipController.prototype.unbindDocumentEvents = function () { - document.removeEventListener("s-popover:shown", this.boundHideIfWithin); - }; - TooltipController.prototype.generatePopover = function () { - return this.applyTitleAttributes(); - }; - TooltipController.prototype.hideIfWithin = function (event) { - if (event.target.contains(this.referenceElement)) { - this.hide(); - } - }; - TooltipController.prototype.bindMouseEvents = function () { - this.boundScheduleShow = this.boundScheduleShow || this.scheduleShow.bind(this); - this.boundHide = this.boundHide || this.hide.bind(this); - this.referenceElement.addEventListener("mouseover", this.boundScheduleShow); - this.referenceElement.addEventListener("mouseout", this.boundHide); - }; - TooltipController.prototype.unbindMouseEvents = function () { - this.referenceElement.removeEventListener("mouseover", this.boundScheduleShow); - this.referenceElement.removeEventListener("mouseout", this.boundHide); - }; - TooltipController.generateId = function () { - return "--stacks-s-tooltip-" + Math.random().toString(36).substring(2, 10); - }; - TooltipController.targets = []; - return TooltipController; - }(Stacks.BasePopoverController)); - Stacks.TooltipController = TooltipController; - function setTooltipHtml(element, html, options) { - element.setAttribute("data-s-tooltip-html-title", html); - element.removeAttribute("title"); - applyOptionsAndTitleAttributes(element, options); - } - Stacks.setTooltipHtml = setTooltipHtml; - function setTooltipText(element, text, options) { - element.setAttribute("title", text); - element.removeAttribute("data-s-tooltip-html-title"); - applyOptionsAndTitleAttributes(element, options); - } - Stacks.setTooltipText = setTooltipText; - function applyOptionsAndTitleAttributes(element, options) { - if (options && options.placement) { - element.setAttribute("data-s-tooltip-placement", options.placement); - } - var controller = Stacks.application.getControllerForElementAndIdentifier(element, "s-tooltip"); - if (controller) { - controller.applyTitleAttributes(); - } - else { - element.setAttribute("data-controller", element.getAttribute("data-controller") + " s-tooltip"); - } - } -})(Stacks || (Stacks = {})); -Stacks.application.register("s-tooltip", Stacks.TooltipController); -//# sourceMappingURL=s-tooltip.js.map - -; - -"use strict"; -Stacks._initializing = false; -//# sourceMappingURL=finalize.js.map \ No newline at end of file diff --git a/dist/js/stacks.min.js b/dist/js/stacks.min.js deleted file mode 100644 index d507105898..0000000000 --- a/dist/js/stacks.min.js +++ /dev/null @@ -1 +0,0 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.Stimulus={})}(this,function(e){"use strict";var r=(t.prototype.connect=function(){this.eventTarget.addEventListener(this.eventName,this,!1)},t.prototype.disconnect=function(){this.eventTarget.removeEventListener(this.eventName,this,!1)},t.prototype.bindingConnected=function(e){this.unorderedBindings.add(e)},t.prototype.bindingDisconnected=function(e){this.unorderedBindings.delete(e)},t.prototype.handleEvent=function(e){for(var t=function(e){if("immediatePropagationStopped"in e)return e;var t=e.stopImmediatePropagation;return Object.assign(e,{immediatePropagationStopped:!1,stopImmediatePropagation:function(){this.immediatePropagationStopped=!0,t.call(this)}})}(e),n=0,r=this.bindings;n)?(.+?)(#(.+))?$/;function s(e){var t=e.trim().match(i)||[];return{eventTarget:function(e){{if("window"==e)return window;if("document"==e)return document}}(t[4]),eventName:t[2],identifier:t[5],methodName:t[7]}}var a=(c.forToken=function(e){return new this(e.element,e.index,s(e.content))},c.prototype.toString=function(){var e=this.eventTargetName?"@"+this.eventTargetName:"";return this.eventName+e+"->"+this.identifier+"#"+this.methodName},Object.defineProperty(c.prototype,"eventTargetName",{get:function(){return(e=this.eventTarget)==window?"window":e==document?"document":void 0;var e},enumerable:!0,configurable:!0}),c);function c(e,t,n){this.element=e,this.index=t,this.eventTarget=n.eventTarget||e,this.eventName=n.eventName||function(e){var t=e.tagName.toLowerCase();if(t in l)return l[t](e)}(e)||u("missing event name"),this.identifier=n.identifier||u("missing identifier"),this.methodName=n.methodName||u("missing method name")}var l={a:function(e){return"click"},button:function(e){return"click"},form:function(e){return"submit"},input:function(e){return"submit"==e.getAttribute("type")?"click":"change"},select:function(e){return"change"},textarea:function(e){return"change"}};function u(e){throw new Error(e)}var p=(Object.defineProperty(f.prototype,"index",{get:function(){return this.action.index},enumerable:!0,configurable:!0}),Object.defineProperty(f.prototype,"eventTarget",{get:function(){return this.action.eventTarget},enumerable:!0,configurable:!0}),Object.defineProperty(f.prototype,"identifier",{get:function(){return this.context.identifier},enumerable:!0,configurable:!0}),f.prototype.handleEvent=function(e){this.willBeInvokedByEvent(e)&&this.invokeWithEvent(e)},Object.defineProperty(f.prototype,"eventName",{get:function(){return this.action.eventName},enumerable:!0,configurable:!0}),Object.defineProperty(f.prototype,"method",{get:function(){var e=this.controller[this.methodName];if("function"==typeof e)return e;throw new Error('Action "'+this.action+'" references undefined method "'+this.methodName+'"')},enumerable:!0,configurable:!0}),f.prototype.invokeWithEvent=function(t){try{this.method.call(this.controller,t)}catch(e){var n={identifier:this.identifier,controller:this.controller,element:this.element,index:this.index,event:t};this.context.handleError(e,'invoking action "'+this.action+'"',n)}},f.prototype.willBeInvokedByEvent=function(e){var t=e.target;return this.element===t||!(t instanceof Element&&this.element.contains(t))||this.scope.containsElement(t)},Object.defineProperty(f.prototype,"controller",{get:function(){return this.context.controller},enumerable:!0,configurable:!0}),Object.defineProperty(f.prototype,"methodName",{get:function(){return this.action.methodName},enumerable:!0,configurable:!0}),Object.defineProperty(f.prototype,"element",{get:function(){return this.scope.element},enumerable:!0,configurable:!0}),Object.defineProperty(f.prototype,"scope",{get:function(){return this.context.scope},enumerable:!0,configurable:!0}),f);function f(e,t){this.context=e,this.action=t}var d=(h.prototype.start=function(){this.started||(this.started=!0,this.mutationObserver.observe(this.element,{attributes:!0,childList:!0,subtree:!0}),this.refresh())},h.prototype.stop=function(){this.started&&(this.mutationObserver.takeRecords(),this.mutationObserver.disconnect(),this.started=!1)},h.prototype.refresh=function(){if(this.started){for(var e=new Set(this.matchElementsInTree()),t=0,n=Array.from(this.elements);ts[0]&&t[1]E[C]&&(L=Q(L));var B=Q(L),M=[];if(i&&M.push(j[T]<=0),a&&M.push(j[L]<=0,j[B]<=0),M.every(function(e){return e})){A=_,x=!1;break}O.set(_,M)}if(x)for(var F=h?3:1;0=r.length&&(o=0),n=r[o],this.switchToTab(n),null!==(t=this.selectedTab)&&void 0!==t&&t.focus()},n.prototype.switchToTab=function(e){var t=this.selectedTab;t!==e&&(this.triggerEvent("select",{oldTab:t,newTab:e}).defaultPrevented||(this.selectedTab=e,this.triggerEvent("selected",{oldTab:t,newTab:e})))},Object.defineProperty(n.prototype,"selectedTab",{get:function(){return this.tabTargets.find(function(e){return"true"===e.getAttribute("aria-selected")})||null},set:function(e){for(var t=0,n=this.tabTargets;tt[0]?n:e[0]t[1]?1:-1}),l.forEach(function(e){var t=r[e[1]];t.parentElement.removeChild(t),u?i.insertBefore(t,u):i.appendChild(t)}),this.setCurrentSort(t,1==n?"asc":"desc"))},(e=n).targets=["column"],e))}();var Stacks,__extends=this&&this.__extends||function(){var r=function(e,t){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}}();!function(r){var n,e=(n=r.BasePopoverController,__extends(a,n),a.prototype.connect=function(){n.prototype.connect.call(this),window.matchMedia("(hover: hover)").matches&&this.bindMouseEvents()},a.prototype.disconnect=function(){this.unbindMouseEvents(),n.prototype.disconnect.call(this)},a.prototype.show=function(e){void 0===e&&(e=null);var t=r.application.getControllerForElementAndIdentifier(this.element,"s-popover");t&&t.isVisible||n.prototype.show.call(this,e)},a.prototype.scheduleShow=function(e){var t=this;void 0===e&&(e=null),window.clearTimeout(this.activeTimeout),this.activeTimeout=window.setTimeout(function(){return t.show(e)},300)},a.prototype.hide=function(e){void 0===e&&(e=null),window.clearTimeout(this.activeTimeout),this.activeTimeout=null,n.prototype.hide.call(this,e)},a.prototype.applyTitleAttributes=function(){var e,t=this.data.get("html-title");if(t)e=document.createRange().createContextualFragment(t);else{var n=this.element.getAttribute("title");if(!n)return null;e=document.createTextNode(n)}this.data.delete("html-title"),this.element.removeAttribute("title");var r=this.element.getAttribute("aria-describedby");r||(r=a.generateId(),this.element.setAttribute("aria-describedby",r));var o,i=document.getElementById(r);i||((i=document.createElement("div")).id=r,i.className="s-popover s-popover__tooltip pe-none",i.setAttribute("aria-hidden","true"),i.setAttribute("role","tooltip"),(o=this.element.parentNode)?o.insertBefore(i,this.element.nextSibling):document.body.appendChild(i));var s=i.querySelector(".s-popover--arrow");return i.innerHTML="",i.appendChild(e),s?i.appendChild(s):i.insertAdjacentHTML("beforeend",'
'),this.scheduleUpdate(),i},a.prototype.bindDocumentEvents=function(){this.boundHideIfWithin=this.boundHideIfWithin||this.hideIfWithin.bind(this),document.addEventListener("s-popover:shown",this.boundHideIfWithin)},a.prototype.unbindDocumentEvents=function(){document.removeEventListener("s-popover:shown",this.boundHideIfWithin)},a.prototype.generatePopover=function(){return this.applyTitleAttributes()},a.prototype.hideIfWithin=function(e){e.target.contains(this.referenceElement)&&this.hide()},a.prototype.bindMouseEvents=function(){this.boundScheduleShow=this.boundScheduleShow||this.scheduleShow.bind(this),this.boundHide=this.boundHide||this.hide.bind(this),this.referenceElement.addEventListener("mouseover",this.boundScheduleShow),this.referenceElement.addEventListener("mouseout",this.boundHide)},a.prototype.unbindMouseEvents=function(){this.referenceElement.removeEventListener("mouseover",this.boundScheduleShow),this.referenceElement.removeEventListener("mouseout",this.boundHide)},a.generateId=function(){return"--stacks-s-tooltip-"+Math.random().toString(36).substring(2,10)},a.targets=[],a);function a(){var e=null!==n&&n.apply(this,arguments)||this;return e.popoverSelectorAttribute="aria-describedby",e}function o(e,t){t&&t.placement&&e.setAttribute("data-s-tooltip-placement",t.placement);var n=r.application.getControllerForElementAndIdentifier(e,"s-tooltip");n?n.applyTitleAttributes():e.setAttribute("data-controller",e.getAttribute("data-controller")+" s-tooltip")}r.TooltipController=e,r.setTooltipHtml=function(e,t,n){e.setAttribute("data-s-tooltip-html-title",t),e.removeAttribute("title"),o(e,n)},r.setTooltipText=function(e,t,n){e.setAttribute("title",t),e.removeAttribute("data-s-tooltip-html-title"),o(e,n)}}(Stacks=Stacks||{}),Stacks.application.register("s-tooltip",Stacks.TooltipController),Stacks._initializing=!1; \ No newline at end of file diff --git a/docs/.eleventy.js b/docs/.eleventy.js index d34f16d02e..a53e7524e2 100644 --- a/docs/.eleventy.js +++ b/docs/.eleventy.js @@ -1,14 +1,39 @@ const hljs = require("highlight.js"); const syntaxHighlight = require("eleventy-plugin-highlightjs"); const pluginTOC = require("eleventy-plugin-nesting-toc"); +const markdownIt = require("markdown-it")("commonmark"); const markdownShortcode = require("eleventy-plugin-markdown-shortcode"); const { default: Icons, Spots } = require("@stackoverflow/stacks-icons"); const { version } = require("../package.json"); +// customize markdown-it rendering to add our classes +markdownIt.use(function(md) { + // mapping of tag: classes + const customClasses = { + "code": "stacks-code" + } + + const addClasses = function(tokens) { + tokens.forEach(function(token) { + if (token.tag in customClasses) { + token.attrJoin("class", customClasses[token.tag]); + } + + if (token.children) { + addClasses(token.children); + } + }); + }; + + md.core.ruler.push("add-custom-classes", function(state) { + addClasses(state.tokens); + }); +}); + module.exports = function(eleventyConfig) { + eleventyConfig.setQuietMode(true); // Reduce the console output eleventyConfig.addLayoutAlias('home', 'layouts/home.html'); eleventyConfig.addLayoutAlias('page', 'layouts/page.html'); - eleventyConfig.addLayoutAlias('page-nomenu', 'layouts/page-nomenu.html'); // Icon shortcode eleventyConfig.addLiquidShortcode("icon", function(name, classes, dimension) { @@ -61,11 +86,11 @@ module.exports = function(eleventyConfig) { var linkIcon = Icons["Link"]; var output = ''; - output += '
'; - output += '<' + tag + ' class="grid--cell fl1 stacks-' + tag + '" id="'+ slug +'">'; + output += '
'; + output += '<' + tag + ' class="flex--item fl-grow1 stacks-' + tag + '" id="'+ slug +'">'; output += '' + text + ''; output += ''; - output += ''; + output += ''; output += 'Section titled ' + text + ''; output += linkIcon; output += ''; @@ -74,11 +99,49 @@ module.exports = function(eleventyConfig) { return output; }); + // Tip shortcode + eleventyConfig.addPairedShortcode("tip", function(content, type, classes, interiorClasses) { + var spot = ""; + + if (type == "warning") { + spot = Spots["Alert"]; + type = "s-notice__warning"; + } else { + spot = Spots["AlertCircle"]; + type = "s-notice__info"; + } + + if (classes == null) { + classes = "mb48"; + } + + if (interiorClasses == null) { + interiorClasses = "ai-start"; + } + + var output = ''; + output += '
'; + output += '
'; + output += '
'; + output += spot; + output += '
'; + output += '
'; + output += content + output += '
'; + output += '
'; + output += '
'; + + return output; + }); + // Version shortcode eleventyConfig.addLiquidShortcode("version", function() { return {version}.version; }); + eleventyConfig.addLiquidFilter("markdown", function(content) { + return markdownIt.renderInline(content); + }); // highlightjs line-numbering support // add `linenums` or `linenums:startNumber` to the start of your code for detection @@ -141,7 +204,7 @@ module.exports = function(eleventyConfig) { highlight: function (str, lang) { if (lang && hljs.getLanguage(lang)) { return '
' +
-               hljs.highlight(lang, str).value +
+               hljs.highlight(str, {language: lang}).value +
                '
'; } diff --git a/docs/404.html b/docs/404.html index be9a35d709..6ab6a8cb25 100755 --- a/docs/404.html +++ b/docs/404.html @@ -6,12 +6,12 @@ {% include head.html %} - -
-
+ +
+
- diff --git a/docs/_data/activity-indicator.json b/docs/_data/activity-indicator.json new file mode 100755 index 0000000000..ba5482f6d1 --- /dev/null +++ b/docs/_data/activity-indicator.json @@ -0,0 +1,24 @@ +{ + "indicator": [ + { + "class": ".s-activity-indicator", + "applies": "N/A", + "description": "Base activity indicator element with theme-aware coloring" + }, + { + "class": ".s-activity-indicator__success", + "applies": ".s-activity-indicator", + "description": "Styles the activity indicator in a success state" + }, + { + "class": ".s-activity-indicator__warning", + "applies": ".s-activity-indicator", + "description": "Styles the activity indicator in a warning state" + }, + { + "class": ".s-activity-indicator__danger", + "applies": ".s-activity-indicator", + "description": "Styles the activity indicator in a danger state" + } + ] +} \ No newline at end of file diff --git a/docs/_data/atomics.json b/docs/_data/atomics.json index 6f607b11d6..0cf1c3b00d 100755 --- a/docs/_data/atomics.json +++ b/docs/_data/atomics.json @@ -2,7 +2,8 @@ "box-shadow": [ { "class": "bs-none", - "output": "box-shadow: none;" + "output": "box-shadow: none;", + "responsive": true }, { "class": "bs-sm", @@ -36,7 +37,7 @@ { "class": "box-border", "output": "box-sizing: border-box;", - "define": "

Indicates that the element's width and height affects the entire element. preferred default value for Stacks.", + "define": "

Indicates that the element's width and height affects the entire element. This is the preferred default value for Stacks.", "responsive": false }, { @@ -171,13 +172,13 @@ "class": "d-flex", "output": "display: flex;", "define": "

Lays out its content according to the flexbox model.

", - "responsive": false + "responsive": true }, { "class": "d-inline-flex", "output": "display: inline-flex;", "define": "

This makes the element behave like an inline element and lays out its content according to the flexbox model.

", - "responsive": false + "responsive": true }, { "class": "d-grid", @@ -1333,5 +1334,37 @@ "define": "

Remove a transition delay from an element.

", "responsive": false } + ], + "object-fit": [ + { + "class": ".of-contain", + "output": "object-fit: contain", + "define": "

Fit the content to the content box while preserving its aspect ratio. This may result in empty space in the content box.

" + }, + { + "class": ".of-cover", + "output": "object-fit: cover", + "define": "

Cover the entire content box with the content while preserving its aspect ratio. This may crop the content.

" + }, + { + "class": ".of-fill", + "output": "object-fit: fill", + "define": "

Stretch and scale the content’s dimensions to match its content box. This is the default browser value.

" + }, + { + "class": ".of-none", + "output": "object-fit: none", + "define": "

Prevent the content from being resized.

" + }, + { + "class": ".of-scale-down", + "output": "object-fit: scale-down", + "define": "

When larger than the content box, resize the content to fill its content box. Otherwise, maintain the content’s original dimensions.

" + }, + { + "class": ".op-center", + "output": "object-position: center", + "define": "

Center the content within its content box.

" + } ] -} \ No newline at end of file +} diff --git a/docs/_data/backgrounds.json b/docs/_data/backgrounds.json index 6e7cce19f0..5f787305ca 100755 --- a/docs/_data/backgrounds.json +++ b/docs/_data/backgrounds.json @@ -82,5 +82,11 @@ "class": ".bg-contain", "output": "background-size: contain;" } + ], + "background-image": [ + { + "class": ".bg-image-none", + "output": "background-image: none;" + } ] } \ No newline at end of file diff --git a/docs/_data/buttons.json b/docs/_data/buttons.json index be45d5cb44..348839a5a8 100755 --- a/docs/_data/buttons.json +++ b/docs/_data/buttons.json @@ -239,16 +239,6 @@ "size": "Medium", "fs": "17px", "class": "s-btn__md" - }, - { - "size": "Large", - "fs": "21px", - "class": "s-btn__lg" - }, - { - "size": "Extra Large", - "fs": "27px", - "class": "s-btn__xl" } ] } \ No newline at end of file diff --git a/docs/_data/colors.json b/docs/_data/colors.json index 38b8dadae6..1478384d9c 100755 --- a/docs/_data/colors.json +++ b/docs/_data/colors.json @@ -1,10 +1,9 @@ [ { "name": "red", - "primary": 500, + "primary": 400, "white": true, "include": true, - "flip": true, "stops": [ { "stop": 900, @@ -29,20 +28,16 @@ { "stop": 500, "hex": "d1383d", - "white": true, - "flip": true + "white": true }, { "stop": 400, "hex": "de535e", - "white": true, - "flip": true + "white": true }, { "stop": 300, - "hex": "e87c87", - "white": true, - "flip": true + "hex": "e87c87" }, { "stop": 200, @@ -92,8 +87,7 @@ { "stop": 400, "hex": "f48024", - "white": true, - "flip": true + "white": true }, { "stop": 300, @@ -115,7 +109,8 @@ }, { "name": "yellow", - "primary": 400, + "primary": 500, + "white": true, "include": true, "stops": [ { @@ -141,12 +136,12 @@ { "stop": 500, "hex": "ddb624", - "white": true, - "flip": true + "white": true }, { "stop": 400, - "hex": "e9c63f" + "hex": "e9c63f", + "white": true }, { "stop": 300, @@ -200,14 +195,11 @@ { "stop": 400, "hex": "5eba7d", - "white": true, - "flip": true + "white": true }, { "stop": 300, - "hex": "82ca9a", - "white": true, - "flip": true + "hex": "82ca9a" }, { "stop": 200, @@ -251,26 +243,21 @@ { "stop": 600, "hex": "0077cc", - "white": true, - "flip": true + "white": true }, { "stop": 500, "hex": "0095ff", - "white": true, - "flip": true + "white": true }, { "stop": 400, "hex": "379fef", - "white": true, - "flip": true + "white": true }, { "stop": 300, - "hex": "6cbbf7", - "white": true, - "flip": true + "hex": "6cbbf7" }, { "stop": 200, @@ -288,7 +275,7 @@ }, { "name": "powder", - "primary": 600, + "primary": 500, "white": true, "include": true, "stops": [ @@ -315,12 +302,12 @@ { "stop": 500, "hex": "7aa7c7", - "white": true, - "flip": true + "white": true }, { "stop": 400, - "hex": "a0c7e4" + "hex": "a0c7e4", + "white": true }, { "stop": 300, @@ -384,14 +371,12 @@ { "stop": 350, "hex": "9199a1", - "white": true, - "flip": true + "white": true }, { "stop": 300, "hex": "9fa6ad", - "white": true, - "flip": true + "white": true }, { "stop": 200, @@ -419,16 +404,125 @@ } ] }, + { + "name": "theme-primary", + "primary": 400, + "white": true, + "stops": [ + { + "stop": 900, + "white": true + }, + { + "stop": 800, + "white": true + }, + { + "stop": 700, + "white": true + }, + { + "stop": 600, + "white": true + }, + { + "stop": 500, + "white": true + }, + { + "stop": 400, + "white": true + }, + { + "stop": 350 + }, + { + "stop": 300 + }, + { + "stop": 200 + }, + { + "stop": 150 + }, + { + "stop": 100 + }, + { + "stop": "075" + }, + { + "stop": "050" + }, + { + "stop": "025" + } + ] + }, + { + "name": "theme-secondary", + "primary": 400, + "white": true, + "stops": [ + { + "stop": 900, + "white": true + }, + { + "stop": 800, + "white": true + }, + { + "stop": 700, + "white": true + }, + { + "stop": 600, + "white": true + }, + { + "stop": 500, + "white": true + }, + { + "stop": 400, + "white": true + }, + { + "stop": 350 + }, + { + "stop": 300 + }, + { + "stop": 200 + }, + { + "stop": 150 + }, + { + "stop": 100 + }, + { + "stop": "075" + }, + { + "stop": "050" + }, + { + "stop": "025" + } + ] + }, { "name": "gold", "primary": "", - "include": false, "flip": true, "stops": [ { "stop": "darker", "hex": "f1b600", - "flip": true + "white": true }, { "stop": "", @@ -444,13 +538,12 @@ { "name": "silver", "primary": "", - "include": false, "flip": true, "stops": [ { "stop": "darker", "hex": "9a9c9f", - "flip": true + "white": true }, { "stop": "", @@ -466,13 +559,12 @@ { "name": "bronze", "primary": "", - "include": false, "flip": true, "stops": [ { "stop": "darker", "hex": "ab825f", - "flip": true + "white": true }, { "stop": "", @@ -485,4 +577,4 @@ } ] } -] \ No newline at end of file +] diff --git a/docs/_data/grids.json b/docs/_data/flex.json similarity index 57% rename from docs/_data/grids.json rename to docs/_data/flex.json index 77859ce7e0..2355e3d6c7 100755 --- a/docs/_data/grids.json +++ b/docs/_data/flex.json @@ -1,63 +1,63 @@ { - "grid-cell": [ + "flex-item": [ { - "class": ".grid--cell1", - "all": ".grid__allcells1", + "class": ".flex--item1", + "all": ".flex__allitems1", "output": "flex-basis: 8.333333333%;" }, { - "class": ".grid--cell2", - "all": ".grid__allcells2", + "class": ".flex--item2", + "all": ".flex__allitems2", "output": "flex-basis: 16.666666667%;" }, { - "class": ".grid--cell3", - "all": ".grid__allcells3", + "class": ".flex--item3", + "all": ".flex__allitems3", "output": "flex-basis: 24.999999999%;" }, { - "class": ".grid--cell4", - "all": ".grid__allcells4", + "class": ".flex--item4", + "all": ".flex__allitems4", "output": "flex-basis: 33.333333332%;" }, { - "class": ".grid--cell5", - "all": ".grid__allcells5", + "class": ".flex--item5", + "all": ".flex__allitems5", "output": "flex-basis: 41.666666665%;" }, { - "class": ".grid--cell6", - "all": ".grid__allcells6", + "class": ".flex--item6", + "all": ".flex__allitems6", "output": "flex-basis: 50%;" }, { - "class": ".grid--cell7", - "all": ".grid__allcells7", + "class": ".flex--item7", + "all": ".flex__allitems7", "output": "flex-basis: 58.333333331%;" }, { - "class": ".grid--cell8", - "all": ".grid__allcells8", + "class": ".flex--item8", + "all": ".flex__allitems8", "output": "flex-basis: 66.666666664%;" }, { - "class": ".grid--cell9", - "all": ".grid__allcells9", + "class": ".flex--item9", + "all": ".flex__allitems9", "output": "flex-basis: 74.999999997%;" }, { - "class": ".grid--cell10", - "all": ".grid__allcells10", + "class": ".flex--item10", + "all": ".flex__allitems10", "output": "flex-basis: 83.33333333%;" }, { - "class": ".grid--cell11", - "all": ".grid__allcells11", + "class": ".flex--item11", + "all": ".flex__allitems11", "output": "flex-basis: 91.666666663%;" }, { - "class": ".grid--cell12", - "all": ".grid__allcells12", + "class": ".flex--item12", + "all": ".flex__allitems12", "output": "flex-basis: 100%;" } ], @@ -111,37 +111,39 @@ "output": "Applies margins only to top and bottom" } ], - "atomic": [ + "justification": [ { - "class": ".ac-center", - "define": "Distributes child elements starting from the center along a parent’s cross axis. This only works with more than one line.", - "responsive": false + "class": ".jc-center", + "define": "Centers child elements along the parent’s main axis.", + "responsive": true }, { - "class": ".ac-end", - "define": "Distributes child elements starting from the end along a parent’s cross axis. This only works with more than one line.", - "responsive": false + "class": ".jc-end", + "define": "Aligns child elements at the end of the parent’s main axis.", + "responsive": true }, { - "class": ".ac-space-around", - "define": "Distributes child elements with space around along a parent’s cross axis. This only works with more than one line.", - "responsive": false + "class": ".jc-space-around", + "define": "Equally distributes the remaining space around child elements. Note that this doesn’t mean the spaces are visually equal, but that the same space unit is applied to both sides of a child element. The first item would have one unit of space against the container edge, but the next item would have two units of space between itself and the first item.", + "responsive": true }, { - "class": ".ac-space-between", - "define": "Distributes child elements with space between along a parent’s cross axis. This only works with more than one line.", - "responsive": false + "class": ".jc-space-between", + "define": "Evenly distributes the space between child elements along a parent’s main axis with the first item starting on the start line and the last item on the end line.", + "responsive": true }, { - "class": ".ac-start", - "define": "Distributes child elements starting from the start along a parent’s cross axis. This only works with more than one line.", - "responsive": false + "class": ".jc-space-evenly", + "define": "The spacing between any two items (and spacing between the edges) are equal.", + "responsive": true }, { - "class": ".ac-stretch", - "define": "Distributes child elements stretching them along a parent’s cross axis. This only works with more than one line.", - "responsive": false - }, + "class": ".jc-start", + "define": "Aligns child elements at the start of the parent’s main axis.", + "responsive": true + } + ], + "align-items": [ { "class": ".ai-baseline", "define": "Aligns child elements along the baseline of a parent’s cross axis.", @@ -166,37 +168,9 @@ "class": ".ai-stretch", "define": "Stretches child elements along the parent’s cross axis.", "responsive": true - }, - { - "class": ".as-auto", - "define": "Auto re-aligns a child element along the parent’s main axis.", - "responsive": true - }, - { - "class": ".as-baseline", - "define": "Re-aligns a child element along the baseline of the parent’s main axis.", - "responsive": true - }, - { - "class": ".as-center", - "define": "Centers a child element along the parent’s main axis.", - "responsive": true - }, - { - "class": ".as-end", - "define": "Re-aligns a child element to the end of the parent’s main axis.", - "responsive": true - }, - { - "class": ".as-start", - "define": "Re-aligns a child element to the start of the parent’s main axis.", - "responsive": true - }, - { - "class": ".as-stretch", - "define": "Stretches a child element along the parent’s main axis.", - "responsive": true - }, + } + ], + "flex-direction": [ { "class": ".fd-row", "define": "Sets the flex direction to a row.", @@ -216,147 +190,73 @@ "class": ".fd-column-reverse", "define": "Reverses the column flex direction.", "responsive": true - }, - { - "class": ".ff-row-wrap", - "define": "Shortand property to set flex direction and wrap to row wrap.", - "responsive": false - }, - { - "class": ".ff-row-nowrap", - "define": "Shortand property to set flex direction and wrap to row nowrap.", - "responsive": false - }, + } + ], + "align-content": [ { - "class": ".ff-row-reverse-wrap", - "define": "Shortand property to set flex direction and wrap to row-reverse wrap.", + "class": ".ac-center", + "define": "Distributes child elements starting from the center along a parent’s cross axis. This only works with more than one line.", "responsive": false }, { - "class": ".ff-row-reverse-nowrap", - "define": "Shortand property to set flex direction and wrap to row-reverse nowrap.", + "class": ".ac-end", + "define": "Distributes child elements starting from the end along a parent’s cross axis. This only works with more than one line.", "responsive": false }, { - "class": ".ff-column-wrap", - "define": "Shortand property to set flex direction and wrap to column wrap.", + "class": ".ac-space-around", + "define": "Distributes child elements with space around along a parent’s cross axis. This only works with more than one line.", "responsive": false }, { - "class": ".ff-column-nowrap", - "define": "Shortand property to set flex direction and wrap to column nowrap.", + "class": ".ac-space-between", + "define": "Distributes child elements with space between along a parent’s cross axis. This only works with more than one line.", "responsive": false }, { - "class": ".ff-column-reverse-wrap", - "define": "Shortand property to set flex direction and wrap to column-reverse wrap.", + "class": ".ac-start", + "define": "Distributes child elements starting from the start along a parent’s cross axis. This only works with more than one line.", "responsive": false }, { - "class": ".ff-column-reverse-nowrap", - "define": "Shortand property to set flex direction and wrap to column-reverse nowrap.", + "class": ".ac-stretch", + "define": "Distributes child elements stretching them along a parent’s cross axis. This only works with more than one line.", "responsive": false - }, + } + ], + "align-self": [ { - "class": ".fl0", - "define": "Sets flex grow and shrink to 0, flex-basis to auto.", + "class": ".as-auto", + "define": "Auto re-aligns a child element along the parent’s main axis based on the ai-[x] value.", "responsive": true }, { - "class": ".fl1", - "define": "Sets flex grow and shrink to 1, flex-basis to auto.", + "class": ".as-baseline", + "define": "Re-aligns a child element along the baseline of the parent’s main axis.", "responsive": true }, { - "class": ".fl2", - "define": "Sets flex grow and shrink to 2, flex-basis to auto.", - "responsive": false - }, - { - "class": ".fl3", - "define": "Sets flex grow and shrink to 3, flex-basis to auto.", - "responsive": false - }, - { - "class": ".fl4", - "define": "Sets flex grow and shrink to 4, flex-basis to auto.", - "responsive": false - }, - { - "class": ".fl5", - "define": "Sets flex grow and shrink to 5, flex-basis to auto.", - "responsive": false - }, - { - "class": ".fl-shrink0", - "define": "Sets flex shrink value to 0, which means it won’t shrink relative to available space and sibling elements.", - "responsive": false - }, - { - "class": ".fl-shrink1", - "define": "Sets flex shrink value to 1. This means it will shrink relative to other sibling elements by a factor of 1.", - "responsive": false - }, - { - "class": ".fl-shrink2", - "define": "Sets flex shrink value to 2. This means it will shrink relative to other sibling elements by a factor of 2.", - "responsive": false - }, - { - "class": ".fl-shrink3", - "define": "Sets flex shrink value to 3. This means it will shrink relative to other sibling elements by a factor of 3.", - "responsive": false - }, - { - "class": ".fl-shrink4", - "define": "Sets flex shrink value to 4. This means it will shrink relative to other sibling elements by a factor of 4.", - "responsive": false - }, - { - "class": ".fl-shrink5", - "define": "Sets flex shrink value to 5. This means it will shrink relative to other sibling elements by a factor of 5.", - "responsive": false - }, - { - "class": ".fl-grow0", - "define": "Sets flex grow value to 0, which means it won’t grow relative to available space and sibling elements.", - "responsive": false - }, - { - "class": ".fl-grow1", - "define": "Sets flex grow value to 1. This means it will grow relative to other sibling elements by a factor of 1.", - "responsive": false - }, - { - "class": ".fl-grow2", - "define": "Sets flex grow value to 2. This means it will grow relative to other sibling elements by a factor of 2.", - "responsive": false - }, - { - "class": ".fl-grow3", - "define": "Sets flex grow value to 3. This means it will grow relative to other sibling elements by a factor of 3.", - "responsive": false - }, - { - "class": ".fl-grow4", - "define": "Sets flex grow value to 4. This means it will grow relative to other sibling elements by a factor of 4.", - "responsive": false + "class": ".as-center", + "define": "Centers a child element along the parent’s main axis.", + "responsive": true }, { - "class": ".fl-grow5", - "define": "Sets flex grow value to 5. This means it will grow relative to other sibling elements by a factor of 5.", - "responsive": false + "class": ".as-end", + "define": "Re-aligns a child element to the end of the parent’s main axis.", + "responsive": true }, { - "class": ".fl-none", - "define": "This is equivalent to flex: 0 0 auto. It sizes the item according to its width/height properties, but makes it fully inflexible.", - "responsive": false + "class": ".as-start", + "define": "Re-aligns a child element to the start of the parent’s main axis.", + "responsive": true }, { - "class": ".fl-equal", - "define": "Sets flex grow value to 1, flex shrink to 1, and flex basis to 0, allowing for equal spacing of each child.", - "responsive": false - }, + "class": ".as-stretch", + "define": "Stretches a child element along the parent’s main axis.", + "responsive": true + } + ], + "flex-wrap": [ { "class": ".fw-wrap", "define": "Wraps the child cells within a parent.", @@ -371,51 +271,77 @@ "class": ".fw-nowrap", "define": "Removes the wrap direction.", "responsive": true + } + ], + "order": [ + { + "class": ".order-first", + "define": "Places the child element first within a parent container.", + "responsive": true }, { - "class": ".jc-center", - "define": "Centers child elements along the parent’s main axis.", + "class": ".order-last", + "define": "Places the child element last within a parent container.", + "responsive": true + } + ], + "flex": [ + { + "class": ".fl-grow1", + "define": "Sets flex-grow to allow a flex item to grow to fill any available space.", "responsive": true }, { - "class": ".jc-end", - "define": "Aligns child elements at the end of the parent’s main axis.", + "class": ".fl-grow0", + "define": "Prevents a flex item from growing.", "responsive": true }, { - "class": ".jc-space-around", - "define": "Equally distributes the remaining space around child elements. Note that this doesn’t mean the spaces are visually equal, but that the same space unit is applied to both sides of a child element. The first item would have one unit of space against the container edge, but the next item would have two units of space between itself and the first item.", + "class": ".fl-shrink1", + "define": "Allows a flex item to shrink if needed.", "responsive": true }, { - "class": ".jc-space-between", - "define": "Evenly distributes the space between child elements along a parent’s main axis with the first item starting on the start line and the last item on the end line.", + "class": ".fl-shrink0", + "define": "Prevents a flex item from shrinking.", "responsive": true }, { - "class": ".jc-space-evenly", - "define": "The spacing between any two items (and spacing between the edges) are equal.", + "class": ".fl-none", + "define": "Prevents a flex item from growing or shrinking.", "responsive": true }, { - "class": ".jc-start", - "define": "Aligns child elements at the start of the parent’s main axis.", + "class": ".fl-initial", + "define": "Allows a flex item to shrink but not grow, taking into account its initial size.", + "responsive": true + }, + { + "class": ".fl-auto", + "define": "Allows a flex item to grow and shrink, taking into account its initial size.", "responsive": true }, { - "class": ".grid__center", + "class": ".fl-equal", + "define": "Allow a flex item to grow and shrink as needed, ignoring its initial size. If all children within a flex layout have ..fl-equal enabled, they’ll be the same size. See also .flex__fl-equal", + "responsive": true + } + ], + "helpers": [ + { + "class": ".flex__center", "define": "Centers child elements along a parent’s main and cross axis.", "responsive": false }, { - "class": ".order-first", - "define": "Places the child element first within a parent container.", - "responsive": true + "class": ".flex__fl-shrink0", + "define": "Disables shrinking from all child elements", + "responsive": false }, { - "class": ".order-last", - "define": "Places the child element last within a parent container.", - "responsive": true + "class": ".flex__fl-equal", + "define": "Makes each child element grow equally", + "responsive": false } ] } \ No newline at end of file diff --git a/docs/_data/grid.json b/docs/_data/grid.json new file mode 100644 index 0000000000..51a3ade610 --- /dev/null +++ b/docs/_data/grid.json @@ -0,0 +1,769 @@ +{ + "containers": [ + { + "class": "d-grid", + "output": "display: grid;", + "define": "This turns any element into a block-level element." + } + ], + "column-templates": [ + { + "class": "grid__1", + "output": "grid-template-columns: repeat(1, minmax(0, 1fr))", + "define": "Creates a grid layout with 1 column", + "responsive": true + }, + { + "class": "grid__2", + "output": "grid-template-columns: repeat(2, minmax(0, 2fr))", + "define": "Creates a grid layout with 2 columns", + "responsive": true + }, + { + "class": "grid__3", + "output": "grid-template-columns: repeat(3, minmax(0, 3fr))", + "define": "Creates a grid layout with 3 columns", + "responsive": true + }, + { + "class": "grid__4", + "output": "grid-template-columns: repeat(4, minmax(0, 4fr))", + "define": "Creates a grid layout with 4 columns", + "responsive": true + }, + { + "class": "grid__5", + "output": "grid-template-columns: repeat(5, minmax(0, 5fr))", + "define": "Creates a grid layout with 5 columns", + "responsive": true + }, + { + "class": "grid__6", + "output": "grid-template-columns: repeat(6, minmax(0, 6fr))", + "define": "Creates a grid layout with 6 columns", + "responsive": true + }, + { + "class": "grid__7", + "output": "grid-template-columns: repeat(7, minmax(0, 7fr))", + "define": "Creates a grid layout with 7 columns", + "responsive": true + }, + { + "class": "grid__8", + "output": "grid-template-columns: repeat(8, minmax(0, 8fr))", + "define": "Creates a grid layout with 8 columns", + "responsive": true + }, + { + "class": "grid__9", + "output": "grid-template-columns: repeat(9, minmax(0, 9fr))", + "define": "Creates a grid layout with 9 columns", + "responsive": true + }, + { + "class": "grid__10", + "output": "grid-template-columns: repeat(10, minmax(0, 10fr))", + "define": "Creates a grid layout with 10 columns", + "responsive": true + }, + { + "class": "grid__11", + "output": "grid-template-columns: repeat(11, minmax(0, 11fr))", + "define": "Creates a grid layout with 11 columns", + "responsive": true + }, + { + "class": "grid__12", + "output": "grid-template-columns: repeat(1, minmax(0, 12fr))", + "define": "Creates a grid layout with 12 columns", + "responsive": true + } + ], + "columns": [ + { + "class": "grid--col-all", + "output": "grid-column: 1 / -1", + "define": "Span all the columns", + "responsive": true + }, + { + "class": "grid--col1", + "output": "grid-column: span 1", + "define": "Span 1 column", + "responsive": true + }, + { + "class": "grid--col2", + "output": "grid-column: span 2", + "define": "Span 2 columns", + "responsive": true + }, + { + "class": "grid--col3", + "output": "grid-column: span 3", + "define": "Span 3 columns", + "responsive": true + }, + { + "class": "grid--col4", + "output": "grid-column: span 4", + "define": "Span 4 columns", + "responsive": true + }, + { + "class": "grid--col5", + "output": "grid-column: span 5", + "define": "Span 5 columns", + "responsive": true + }, + { + "class": "grid--col6", + "output": "grid-column: span 6", + "define": "Span 6 columns", + "responsive": true + }, + { + "class": "grid--col7", + "output": "grid-column: span 7", + "define": "Span 7 columns", + "responsive": true + }, + { + "class": "grid--col8", + "output": "grid-column: span 8", + "define": "Span 8 columns", + "responsive": true + }, + { + "class": "grid--col9", + "output": "grid-column: span 9", + "define": "Span 9 columns", + "responsive": true + }, + { + "class": "grid--col10", + "output": "grid-column: span 10", + "define": "Span 10 columns", + "responsive": true + }, + { + "class": "grid--col11", + "output": "grid-column: span 11", + "define": "Span 11 columns", + "responsive": true + }, + { + "class": "grid--col12", + "output": "grid-column: span 12", + "define": "Span 12 columns", + "responsive": true + } + ], + "rows": [ + { + "class": "grid--row-all", + "output": "grid-row: 1 / -1", + "define": "Span all the rows", + "responsive": true + }, + { + "class": "grid--row1", + "output": "grid-row: span 1", + "define": "Span 1 row", + "responsive": true + }, + { + "class": "grid--row2", + "output": "grid-row: span 2", + "define": "Span 2 rows", + "responsive": true + }, + { + "class": "grid--row3", + "output": "grid-row: span 3", + "define": "Span 3 rows", + "responsive": true + }, + { + "class": "grid--row4", + "output": "grid-row: span 4", + "define": "Span 4 rows", + "responsive": true + }, + { + "class": "grid--row5", + "output": "grid-row: span 5", + "define": "Span 5 rows", + "responsive": true + }, + { + "class": "grid--row6", + "output": "grid-row: span 6", + "define": "Span 6 rows", + "responsive": true + }, + { + "class": "grid--row7", + "output": "grid-row: span 7", + "define": "Span 7 rows", + "responsive": true + }, + { + "class": "grid--row8", + "output": "grid-row: span 8", + "define": "Span 8 rows", + "responsive": true + }, + { + "class": "grid--row9", + "output": "grid-row: span 9", + "define": "Span 9 rows", + "responsive": true + }, + { + "class": "grid--row10", + "output": "grid-row: span 10", + "define": "Span 10 rows", + "responsive": true + }, + { + "class": "grid--row11", + "output": "grid-row: span 11", + "define": "Span 11 rows", + "responsive": true + }, + { + "class": "grid--row12", + "output": "grid-row: span 12", + "define": "Span 12 rows", + "responsive": true + } + ], + "spacing": [ + { + "class": "g0", + "output": "gap: 0", + "define": "Add no space between grid items", + "responsive": true + }, + { + "class": "g1", + "output": "gap: 1px", + "define": "Space out grid items by 1px", + "responsive": true + }, + { + "class": "g2", + "output": "gap: 2px", + "define": "Space out grid items by 2px", + "responsive": true + }, + { + "class": "g4", + "output": "gap: 4px", + "define": "Space out grid items by 4px", + "responsive": true + }, + { + "class": "g6", + "output": "gap: 6px", + "define": "Space out grid items by 6px", + "responsive": true + }, + { + "class": "g8", + "output": "gap: 8px", + "define": "Space out grid items by 8px", + "responsive": true + }, + { + "class": "g12", + "output": "gap: 12px", + "define": "Space out grid items by 12px", + "responsive": true + }, + { + "class": "g16", + "output": "gap: 16px", + "define": "Space out grid items by 16px", + "responsive": true + }, + { + "class": "g24", + "output": "gap: 24px", + "define": "Space out grid items by 24px", + "responsive": true + }, + { + "class": "g32", + "output": "gap: 32px", + "define": "Space out grid items by 32px", + "responsive": true + }, + { + "class": "g48", + "output": "gap: 48px", + "define": "Space out grid items by 48px", + "responsive": true + }, + { + "class": "g64", + "output": "gap: 64px", + "define": "Space out grid items by 64px", + "responsive": true + } + ], + "autoflow": [ + { + "class": "g-af-row", + "output": "grid-auto-flow: row", + "define": "Items are placed by filling each row in turn, adding new rows as necessary. The default.", + "responsive": true + }, + { + "class": "g-af-column", + "output": "grid-auto-flow: column", + "define": "Items are placed by filling each column in turn, adding new columns as necessary.", + "responsive": true + }, + { + "class": "g-af-dense", + "output": "grid-auto-flow: dense", + "define": "Dense packing algorithm attempts to fill in holes earlier in the grid, if smaller items come up later. This may cause items to appear out-of-order, when doing so would fill in holes left by larger items.", + "responsive": true + } + ], + "column-start-end": [ + { + "class": "grid--col-start1", + "output": "grid-column-start: 1", + "define": "Start at the 1st column", + "responsive": true + }, + { + "class": "grid--col-start2", + "output": "grid-column-start: 2", + "define": "Start at the 2nd column", + "responsive": true + }, + { + "class": "grid--col-start3", + "output": "grid-column-start: 3", + "define": "Start at the 3rd column", + "responsive": true + }, + { + "class": "grid--col-start4", + "output": "grid-column-start: 4", + "define": "Start at the 4th column", + "responsive": true + }, + { + "class": "grid--col-start5", + "output": "grid-column-start: 5", + "define": "Start at the 5th column", + "responsive": true + }, + { + "class": "grid--col-start6", + "output": "grid-column-start: 6", + "define": "Start at the 6th column", + "responsive": true + }, + { + "class": "grid--col-start7", + "output": "grid-column-start: 7", + "define": "Start at the 7th column", + "responsive": true + }, + { + "class": "grid--col-start8", + "output": "grid-column-start: 8", + "define": "Start at the 8th column", + "responsive": true + }, + { + "class": "grid--col-start9", + "output": "grid-column-start: 9", + "define": "Start at the 9th column", + "responsive": true + }, + { + "class": "grid--col-start10", + "output": "grid-column-start: 10", + "define": "Start at the 10th column", + "responsive": true + }, + { + "class": "grid--col-start11", + "output": "grid-column-start: 11", + "define": "Start at the 11th column", + "responsive": true + }, + { + "class": "grid--col-start12", + "output": "grid-column-start: 12", + "define": "Start at the 12th column", + "responsive": true + }, + { + "class": "grid--col-end2", + "output": "grid-column-end: 2", + "define": "End at the start of 2nd column", + "responsive": true + }, + { + "class": "grid--col-end3", + "output": "grid-column-end: 3", + "define": "End at the start of 3rd column", + "responsive": true + }, + { + "class": "grid--col-end4", + "output": "grid-column-end: 4", + "define": "End at the start of 4th column", + "responsive": true + }, + { + "class": "grid--col-end5", + "output": "grid-column-end: 5", + "define": "End at the start of 5th column", + "responsive": true + }, + { + "class": "grid--col-end6", + "output": "grid-column-end: 6", + "define": "End at the start of 6th column", + "responsive": true + }, + { + "class": "grid--col-end7", + "output": "grid-column-end: 7", + "define": "End at the start of 7th column", + "responsive": true + }, + { + "class": "grid--col-end8", + "output": "grid-column-end: 8", + "define": "End at the start of 8th column", + "responsive": true + }, + { + "class": "grid--col-end9", + "output": "grid-column-end: 9", + "define": "End at the start of 9th column", + "responsive": true + }, + { + "class": "grid--col-end10", + "output": "grid-column-end: 10", + "define": "End at the start of 10th column", + "responsive": true + }, + { + "class": "grid--col-end11", + "output": "grid-column-end: 11", + "define": "End at the start of 11th column", + "responsive": true + }, + { + "class": "grid--col-end12", + "output": "grid-column-end: 12", + "define": "End at the start of 12th column", + "responsive": true + }, + { + "class": "grid--col-end13", + "output": "grid-column-end: 13", + "define": "End at the start of 13th column", + "responsive": true + } + ], + "row-start-end": [ + { + "class": "grid--row-start1", + "output": "grid-row-start: 1", + "define": "Start at the 1st row", + "responsive": true + }, + { + "class": "grid--row-start2", + "output": "grid-row-start: 2", + "define": "Start at the 2nd row", + "responsive": true + }, + { + "class": "grid--row-start3", + "output": "grid-row-start: 3", + "define": "Start at the 3rd row", + "responsive": true + }, + { + "class": "grid--row-start4", + "output": "grid-row-start: 4", + "define": "Start at the 4th row", + "responsive": true + }, + { + "class": "grid--row-start5", + "output": "grid-row-start: 5", + "define": "Start at the 5th row", + "responsive": true + }, + { + "class": "grid--row-start6", + "output": "grid-row-start: 6", + "define": "Start at the 6th row", + "responsive": true + }, + { + "class": "grid--row-start7", + "output": "grid-row-start: 7", + "define": "Start at the 7th row", + "responsive": true + }, + { + "class": "grid--row-start8", + "output": "grid-row-start: 8", + "define": "Start at the 8th row", + "responsive": true + }, + { + "class": "grid--row-start9", + "output": "grid-row-start: 9", + "define": "Start at the 9th row", + "responsive": true + }, + { + "class": "grid--row-start10", + "output": "grid-row-start: 10", + "define": "Start at the 10th row", + "responsive": true + }, + { + "class": "grid--row-start11", + "output": "grid-row-start: 11", + "define": "Start at the 11th row", + "responsive": true + }, + { + "class": "grid--row-start12", + "output": "grid-row-start: 12", + "define": "Start at the 12th row", + "responsive": true + }, + { + "class": "grid--row-end2", + "output": "grid-row-end: 2", + "define": "End at the start of 2nd row", + "responsive": true + }, + { + "class": "grid--row-end3", + "output": "grid-row-end: 3", + "define": "End at the start of 3rd row", + "responsive": true + }, + { + "class": "grid--row-end4", + "output": "grid-row-end: 4", + "define": "End at the start of 4th row", + "responsive": true + }, + { + "class": "grid--row-end5", + "output": "grid-row-end: 5", + "define": "End at the start of 5th row", + "responsive": true + }, + { + "class": "grid--row-end6", + "output": "grid-row-end: 6", + "define": "End at the start of 6th row", + "responsive": true + }, + { + "class": "grid--row-end7", + "output": "grid-row-end: 7", + "define": "End at the start of 7th row", + "responsive": true + }, + { + "class": "grid--row-end8", + "output": "grid-row-end: 8", + "define": "End at the start of 8th row", + "responsive": true + }, + { + "class": "grid--row-end9", + "output": "grid-row-end: 9", + "define": "End at the start of 9th row", + "responsive": true + }, + { + "class": "grid--row-end10", + "output": "grid-row-end: 10", + "define": "End at the start of 10th row", + "responsive": true + }, + { + "class": "grid--row-end11", + "output": "grid-row-end: 11", + "define": "End at the start of 11th row", + "responsive": true + }, + { + "class": "grid--row-end12", + "output": "grid-row-end: 12", + "define": "End at the start of 12th row", + "responsive": true + }, + { + "class": "grid--row-end13", + "output": "grid-row-end: 13", + "define": "End at the start of 13th row", + "responsive": true + } + ], + "alignment": [ + { + "class": "ji-auto", + "output": "justify-items: auto", + "define": "Use the parent’s justify value.", + "responsive": true + }, + { + "class": "ji-center", + "output": "justify-items: center", + "define": "The items are packed flush to each other toward the center of x axis.", + "responsive": true + }, + { + "class": "ji-start", + "output": "justify-items: start", + "define": "The items are packed flush to each other toward the left.", + "responsive": true + }, + { + "class": "ji-end", + "output": "justify-items: end", + "define": "The items are packed flush to each other toward the right.", + "responsive": true + }, + { + "class": "ji-stretch", + "output": "justify-items: stretch", + "define": "Items stretch to fill the available space", + "responsive": true + }, + { + "class": "ji-unset", + "output": "justify-items: unset", + "define": "Removes any justification, effectively resetting the value", + "responsive": true + }, + { + "class": "js-auto", + "output": "justify-self: auto", + "define": "Use the parent’s justify value.", + "responsive": true + }, + { + "class": "js-center", + "output": "justify-self: center", + "define": "The item is packed flush to the others toward the center of x axis.", + "responsive": true + }, + { + "class": "js-start", + "output": "justify-self: start", + "define": "The item is packed flush to the others toward the left.", + "responsive": true + }, + { + "class": "js-end", + "output": "justify-self: end", + "define": "The item is packed flush to the others toward the right.", + "responsive": true + }, + { + "class": "js-stretch", + "output": "justify-self: stretch", + "define": "Item stretches to fill the available space", + "responsive": true + }, + { + "class": "js-unset", + "output": "justify-self: unset", + "define": "Removes any justification, effectively resetting the value", + "responsive": true + }, + { + "class": "ai-baseline", + "output": "align-items: baseline", + "define": "Aligns items along the baseline of a parent’s cross axis.", + "responsive": true + }, + { + "class": "ai-center", + "output": "align-items: center", + "define": "Centers child elements along the parent’s cross axis.", + "responsive": true + }, + { + "class": "ai-end", + "output": "align-items: end", + "define": "Places child elements at the end of the parent’s cross axis.", + "responsive": true + }, + { + "class": "ai-start", + "output": "align-items: start", + "define": "Places child elements at the start of the parent’s cross axis.", + "responsive": true + }, + { + "class": "ai-stretch", + "output": "align-items: stretch", + "define": "Stretches child elements along the parent’s cross axis.", + "responsive": true + }, + { + "class": "as-auto", + "output": "align-self: auto;", + "define": "Auto re-aligns a child element along the parent’s main axis.", + "responsive": true + }, + { + "class": "as-baseline", + "output": "align-self: baseline;", + "define": "Re-aligns a child element along the baseline of the parent’s main axis.", + "responsive": true + }, + { + "class": "as-center", + "output": "align-self: center;", + "define": "Centers a child element along the parent’s main axis.", + "responsive": true + }, + { + "class": "as-end", + "output": "align-self: end;", + "define": "Re-aligns a child element to the end of the parent’s main axis.", + "responsive": true + }, + { + "class": "as-start", + "output": "align-self: start;", + "define": "Re-aligns a child element to the start of the parent’s main axis.", + "responsive": true + }, + { + "class": "as-stretch", + "output": "align-self: stretch;", + "define": "Stretches a child element along the parent’s main axis.", + "responsive": true + } + ] +} \ No newline at end of file diff --git a/docs/_data/links.json b/docs/_data/links.json index d1f20e9b70..cc287e812a 100755 --- a/docs/_data/links.json +++ b/docs/_data/links.json @@ -34,6 +34,11 @@ "class": ".s-link__visited", "applies": "all", "description": "Applies the hover / active state styling to links that have been visited." + }, + { + "class": ".s-link__dropdown", + "applies": ".s-link", + "description": "Applies a caret for dropdowns and additional interactivity." } ], "descendent-anchors": [ @@ -80,7 +85,7 @@ "description": "Base block link style" }, { - "class": ".is_selected", + "class": ".is-selected", "applies": ".s-block-link", "description": "Adds the selected state to the base block link style." }, diff --git a/docs/_data/menu.json b/docs/_data/menu.json new file mode 100755 index 0000000000..0d79a8cf6f --- /dev/null +++ b/docs/_data/menu.json @@ -0,0 +1,24 @@ +{ + "classes": [ + { + "class": ".s-menu", + "applies": "N/A", + "description": "Base container styling for a menu" + }, + { + "class": ".s-menu--title", + "applies": ".s-menu", + "description": "Adds appropriate styling for a title within a menu" + }, + { + "class": ".s-menu--divider", + "applies": ".s-menu", + "description": "Styles a divider and adds the right amount of spacing" + }, + { + "class": ".s-menu--label", + "applies": ".s-menu", + "description": "This gets applied to radio button labels within a menu for proper cursors and aesthetics" + } + ] +} \ No newline at end of file diff --git a/docs/_data/navigation.json b/docs/_data/navigation.json index 6c9861f9e4..bcf2efb0a7 100755 --- a/docs/_data/navigation.json +++ b/docs/_data/navigation.json @@ -34,6 +34,11 @@ "class": ".is-selected", "applies": ".s-navigation--item", "description": "Applies to a navigation item that’s currently selected / active" + }, + { + "class": ".s-navigation--item__dropdown", + "applies": ".s-navigation--item", + "description": "Adds a small caret that indicates a dropdown" } ] } \ No newline at end of file diff --git a/docs/_data/post-summary.json b/docs/_data/post-summary.json new file mode 100755 index 0000000000..fa33e1a979 --- /dev/null +++ b/docs/_data/post-summary.json @@ -0,0 +1,94 @@ +{ + "classes": [ + { + "class": ".s-post-summary", + "applies": "N/A", + "description": "Base parent container for a post summary" + }, + { + "class": ".s-post-summary--stats", + "applies": ".s-post-summary", + "description": "Container for the post summary stats" + }, + { + "class": ".s-post-summary--stats-item", + "applies": ".s-post-summary--stats", + "description": "Individual stat item within the stats container" + }, + { + "class": ".has-answers", + "applies": ".s-post-summary--stats-item", + "description": "Adds the styling necessary for a question with answers" + }, + { + "class": ".has-accepted-answer", + "applies": ".s-post-summary--stats-item", + "description": "Adds the styling necessary for a question with accepted answers" + }, + { + "class": ".has-bounty", + "applies": ".s-post-summary--stats-item", + "description": "Styles the stats item appropriately to display a bounty" + }, + { + "class": ".is-warm", + "applies": ".s-post-summary--stats-item", + "description": "Styles post stats with a warm color" + }, + { + "class": ".is-hot", + "applies": ".s-post-summary--stats-item", + "description": "Warmer still, for more popular posts" + }, + { + "class": ".is-supernova", + "applies": ".s-post-summary--stats-item", + "description": "Paired with a fire icon, these are the most popular stats" + }, + { + "class": ".s-post-summary--content", + "applies": ".s-post-summary", + "description": "Container for the post summary content" + }, + { + "class": ".s-post-summary--content-type", + "applies": ".s-post-summary--content", + "description": "A container for various content types, eg. How-to guide on Articles" + }, + { + "class": ".s-post-summary--content-title", + "applies": ".s-post-summary--content", + "description": "Post title styling" + }, + { + "class": ".s-post-summary--content-excerpt", + "applies": ".s-post-summary--content", + "description": "An optional content excerpt truncated at 2 lines." + }, + { + "class": ".s-post-summary--answer", + "applies": ".s-post-summary--content", + "description": "Adds blockquote styling and spacing for answer previews" + }, + { + "class": ".s-post-summary--answer-excerpt", + "applies": ".s-post-summary--content", + "description": "Provides padding, and truncation to 4 lines." + }, + { + "class": ".s-post-summary--content-menu-button", + "applies": ".s-post-summary--content", + "description": "An optional button for displaying a post-specific menu." + }, + { + "class": ".s-post-summary--meta", + "applies": ".s-post-summary--content", + "description": "A container for post meta data, things like tags and user cards." + }, + { + "class": ".s-post-summary--meta-tags", + "applies": ".s-post-summary--meta", + "description": "A container for tags and other taxonomy." + } + ] +} \ No newline at end of file diff --git a/docs/_data/site-navigation.json b/docs/_data/site-navigation.json index ec771e1d06..4c199f06a6 100755 --- a/docs/_data/site-navigation.json +++ b/docs/_data/site-navigation.json @@ -19,13 +19,17 @@ "title": "Conditional classes", "url": "/product/guidelines/conditional-classes/" }, + { + "title": "JavaScript", + "url": "/product/guidelines/javascript/" + }, { "title": "Releasing Stacks", "url": "/product/guidelines/releasing/" }, { - "title": "JavaScript", - "url": "/product/guidelines/javascript/" + "title": "Theming", + "url": "/product/guidelines/theming/" } ] }, @@ -81,6 +85,10 @@ "title": "Display", "url": "/product/base/display/" }, + { + "title": "Flex", + "url": "/product/base/flex/" + }, { "title": "Floats", "url": "/product/base/floats/" @@ -97,6 +105,10 @@ "title": "Lists", "url": "/product/base/lists/" }, + { + "title": "Object fit", + "url": "/product/base/object-fit/" + }, { "title": "Opacity", "url": "/product/base/opacity/" @@ -150,6 +162,10 @@ { "title": "Components", "links": [ + { + "title": "Activity indicator", + "url": "/product/components/activity-indicator/" + }, { "title": "Avatars", "url": "/product/components/avatars/" @@ -214,6 +230,10 @@ "title": "Link previews", "url": "/product/components/link-previews/" }, + { + "title": "Menus", + "url": "/product/components/menus/" + }, { "title": "Modals", "url": "/product/components/modals/" @@ -238,6 +258,10 @@ "title": "Popovers", "url": "/product/components/popovers/" }, + { + "title": "Post summary", + "url": "/product/components/post-summary/" + }, { "title": "Progress bars", "url": "/product/components/progress-bars/" @@ -278,6 +302,14 @@ "title": "Toggle switch", "url": "/product/components/toggle-switch/" }, + { + "title": "Topbar", + "url": "/product/components/topbar/" + }, + { + "title": "Uploader", + "url": "/product/components/uploader/" + }, { "title": "User cards", "url": "/product/components/user-cards/" @@ -447,14 +479,40 @@ { "title": "Principles", "url": "/brand/principles/" - }, + } + ] + }, + { + "title": "Copywriting", + "links": [ + { + "title": "Naming guidelines", + "url": "/brand/copywriting/naming/" + } + ] + }, + { + "title": "Visuals", + "links": [ { - "title": "Logo", + "title": "Logos", "url": "/brand/logo/" + }, + { + "title": "Typography", + "url": "/brand/typography/" + }, + { + "title": "Colors", + "url": "/brand/colors/" + }, + { + "title": "Data visualization", + "url": "/brand/data-visualization/" } ] } ] } ] -} \ No newline at end of file +} diff --git a/docs/_data/site.json b/docs/_data/site.json index 0e98dc9bf6..eb71d6f593 100644 --- a/docs/_data/site.json +++ b/docs/_data/site.json @@ -1,5 +1,6 @@ { "title": "Stacks", "url": "https://stackoverflow.design", + "description": "Stacks provides everything you need to quickly design, build, and ship coherent experiences across all of Stack Overflow—from the brand and product itself, down to how we send emails and write copy.", "baseurl": "" } \ No newline at end of file diff --git a/docs/_data/spacing.json b/docs/_data/spacing.json index f2b9645a43..0326e9285e 100755 --- a/docs/_data/spacing.json +++ b/docs/_data/spacing.json @@ -2,37 +2,37 @@ "margin": [ { "prefix": "m", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "mt", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "mr", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "ml", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "mb", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "mx", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": false }, { "prefix": "my", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": false } ], @@ -65,37 +65,37 @@ "padding": [ { "prefix": "p", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "pt", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "pr", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "pl", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "pb", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": true }, { "prefix": "px", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": false }, { "prefix": "py", - "values": "0, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", + "values": "0, 1, 2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128", "responsive": false } ], @@ -193,6 +193,10 @@ "term": 0, "define": "0;" }, + { + "term": 1, + "define": "1px;" + }, { "term": 2, "define": "2px;" @@ -280,6 +284,10 @@ "term": 0, "define": "padding: 0;" }, + { + "term": 1, + "define": "padding: 1;" + }, { "term": 2, "define": "padding: 2px;" diff --git a/docs/_data/spinner.json b/docs/_data/spinner.json index 7d8ac2f0d7..3894dde1b1 100755 --- a/docs/_data/spinner.json +++ b/docs/_data/spinner.json @@ -23,7 +23,7 @@ { "class": ".s-spinner__lg", "applies": ".s-spinner", - "description": "A small style for the largest layouts" + "description": "A large style for the largest layouts" } ] -} \ No newline at end of file +} diff --git a/docs/_data/tables.json b/docs/_data/tables.json index 2e628adef2..2aafbc9066 100755 --- a/docs/_data/tables.json +++ b/docs/_data/tables.json @@ -56,7 +56,7 @@ "description": "Wires up the table to the JS controller" }, { - "attribute": "data-target=\"s-table.column\"", + "attribute": "data-s-table-target=\"column\"", "applies": "th", "description": "Marks this is a sortable column for the purpose of modifying arrow icons" }, @@ -80,5 +80,15 @@ "applies": "td", "description": "Optionally use a custom value for sorting instead of the cell’s text content" } + ], + "atomic": [ + { + "class": ".tl-auto", + "output": "table-layout: auto;" + }, + { + "class": ".tl-fixed", + "output": "table-layout: fixed;" + } ] -} \ No newline at end of file +} diff --git a/docs/_data/tags-component.json b/docs/_data/tags-component.json index 8b86d2a7e4..0ebdb8c577 100755 --- a/docs/_data/tags-component.json +++ b/docs/_data/tags-component.json @@ -20,6 +20,11 @@ "applies": ".s-tag", "description": "Applies a visually muted style from the base style." }, + { + "class": ".s-tag__themed", + "applies": ".s-tag", + "description": "Applies a themed color to the tag" + }, { "class": ".s-tag--dismiss", "applies": "N/A", @@ -29,6 +34,11 @@ "class": ".s-tag--sponsor", "applies": "N/A", "description": "A child element within .s-tag that correctly positions a tag’s sponsor logo." + }, + { + "class": ".is-selected", + "applies": ".s-tag", + "description": "Adds a currently selected / active aesthetic" } ], "sizes": [ diff --git a/docs/_data/topbar.json b/docs/_data/topbar.json new file mode 100644 index 0000000000..3886878d98 --- /dev/null +++ b/docs/_data/topbar.json @@ -0,0 +1,66 @@ +[ + { + "class": ".s-topbar", + "description": "Base class" + }, + { + "class": ".s-topbar__light", + "applies": "`.s-topbar`", + "description": "Forced light theme" + }, + { + "class": ".s-topbar__dark", + "applies": "`.s-topbar`", + "description": "Forced dark theme" + }, + { + "class": ".s-topbar--container", + "description": "Add **atomic** `classes` here to customize internal content width; defaults to `.wmx12`", + "applies": "Child of `.s-topbar`" + }, + { + "class": ".s-topbar--logo", + "description": "The logo. Can apply `.is-selected` to this", + "applies": "Child of `.s-topbar`" + }, + { + "class": ".s-topbar--menu-btn", + "description": "Hamburger menu icon. Add `.is-selected` to turn it into an X", + "applies": "Child of `.s-topbar`" + }, + { + "class": ".s-topbar--content", + "description": "Contains `li > .s-topbar--item` elements that don’t look like anything in particular", + "applies": "Child of `.s-topbar`" + }, + { + "class": ".s-topbar--ctas", + "description": "Provides layout for various calls to action, e.g. log in or sign up links. This container provides layout only, leaving child elements to their own styling.", + "applies": "Child of `.s-topbar`" + }, + { + "class": ".s-topbar--item", + "description": "A topbar item element, styles itself based on where it is placed. Can add `.is-selected`", + "applies": "Child of `.s-topbar--content > li`,\n`.s-topbar--ctas > li`" + }, + { + "class": ".s-topbar--notice", + "description": "A badge-styled notice that stands out. Add `.is-unread` to make it stand out more", + "applies": "Child of `.s-topbar`" + }, + { + "class": ".s-topbar--searchbar", + "description": "Contains a search input and an optional `.s-select`. Hides itself on mobile.", + "applies": "Child of `.s-topbar`" + }, + { + "class": ".s-topbar--searchbar--input-group", + "description": "Holds the search input + icon", + "applies": "Child of `.s-topbar--searchbar`" + }, + { + "class": ".s-topbar--searchbar__open", + "applies": "`.s-topbar--searchbar`", + "description": "On mobile, this class shows the search input below the topbar. Toggle this class with a button" + } +] \ No newline at end of file diff --git a/docs/_data/typography.json b/docs/_data/typography.json index 8ff53b8890..483552976e 100755 --- a/docs/_data/typography.json +++ b/docs/_data/typography.json @@ -234,9 +234,9 @@ "define": "Unsets any inherited behavior. Does not work in IE." }, { - "class": "ww-break-word", - "output": "word-wrap: break-word;", - "define": "Deprecated, please use the equivalent ow-break-word instead. Specifies if a browser should insert line breaks within words to prevent text from overflowing its content box." + "class": "break-word", + "output": "word-break: break-word; word-wrap: break-word; overflow-wrap: break-word; hyphens: auto;", + "define": "A utility class combining all word-break strategies when you absolutely must break a word." }, { "class": "wb-normal", diff --git a/docs/_data/uploader-component.json b/docs/_data/uploader-component.json new file mode 100755 index 0000000000..6544b90f49 --- /dev/null +++ b/docs/_data/uploader-component.json @@ -0,0 +1,54 @@ +{ + "classes": [ + { + "class": ".s-uploader", + "applies": "N/A", + "description": "Base uploader element" + }, + { + "class": ".is-active", + "applies": ".s-uploader", + "description": "Active styling for uploader element. Added on dragenter or when input has value." + }, + { + "class": ".is-disabled", + "applies": ".s-uploader", + "description": "Appropriately styles the uploader when it is disabled. Don’t forget to also add the disabled attribute on the input itself." + }, + { + "class": ".has-error", + "applies": ".s-uploader", + "description": "Adds error styling to the component." + }, + { + "class": ".has-success", + "applies": ".s-uploader", + "description": "Adds success styling to the component." + }, + { + "class": ".has-warning", + "applies": ".s-uploader", + "description": "Adds warning styling to the component." + }, + { + "class": ".s-uploader--input", + "applies": "Child of .s-uploader", + "description": "Adds proper styling to the uploader's file input." + }, + { + "class": ".s-uploader--previews", + "applies": "Child of .s-uploader", + "description": "Container for selected item(s) preview." + }, + { + "class": ".s-uploader--preview", + "applies": "Child of .s-uploader--previews", + "description": "An image or string to preview a selected file." + }, + { + "class": ".s-uploader--reset", + "applies": "Child of .s-uploader", + "description": "Used to reset the uploader." + } + ] +} diff --git a/docs/_includes/head.html b/docs/_includes/head.html index cfebb4f8fa..1511d872bf 100755 --- a/docs/_includes/head.html +++ b/docs/_includes/head.html @@ -3,7 +3,7 @@ {% if title %}{{ title | escape }} - {% endif %}{{ site.title | escape }} - + @@ -11,9 +11,9 @@ - - - + + + diff --git a/docs/_includes/header.html b/docs/_includes/header.html index 114953c7ec..d8df586edf 100644 --- a/docs/_includes/header.html +++ b/docs/_includes/header.html @@ -1,48 +1,100 @@ -
-
- - {% icon "Hamburger", "js-hamburger-icon" %} - {% icon "Clear", "d-none js-hamburger-close-icon" %} - -
+ {% if site-navigation %} - + {% endif %} - - {% icon "LogoGlyphSm" %} - - - - {% icon "GitHub", "", "24" %} - +
    +
  1. + + {% icon "LogoGlyphSm" %} + +
  2. +
  3. + + {% icon "GitHub", "", "24" %} + +
  4. +
  5. + + + +
  6. +
- - - + - +
    +
  1. + +
  2. +
  3. + +
  4. +
-
diff --git a/docs/_includes/layouts/home.html b/docs/_includes/layouts/home.html index 2b6e945d2e..50042dea8e 100644 --- a/docs/_includes/layouts/home.html +++ b/docs/_includes/layouts/home.html @@ -2,81 +2,252 @@ {% include head.html %} - - {% include darkmode.html %} -
-
-
- + + {% include theme.html %} +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ {% icon "LogoGlyphSm" %} - + {% icon "GitHub", "", "24" %} - + - - -
-
-

Stacks

- v{% version %} +
+
+

Stacks

+ v{% version %}

Stacks provides everything you need to quickly design, build, and ship coherent experiences across all of Stack Overflow—from the brand and product itself, down to how we send emails and write copy.

-
-
- -
+
+
+ +
{% spot "Puzzle" %}
-
- Product - Robust CSS & JavaScript Pattern libraries for rapidly building Stack Overflow. +
+
Product
+
Robust CSS & JavaScript Pattern libraries for rapidly building Stack Overflow.
- -
+ +
{% spot "Mail" %}
-
- Email - Patterns and guidelines for creating and sending emails to Stack Overflow users. +
+
Email
+
Patterns and guidelines for creating and sending emails to Stack Overflow users.
- -
+ +
{% spot "DocumentAlt" %}
-
- Content - Principles and tactics for writing at Stack Overflow. +
+
Content
+
Principles and tactics for writing at Stack Overflow.
- -
+ +
{% spot "Theme" %}
-
diff --git a/docs/_includes/layouts/page-nomenu.html b/docs/_includes/layouts/page-nomenu.html deleted file mode 100644 index 6500fa3389..0000000000 --- a/docs/_includes/layouts/page-nomenu.html +++ /dev/null @@ -1,30 +0,0 @@ - - -{% include head.html %} - - - {% include darkmode.html %} - {% include header.html %} - -
- {% include navigation.html %} - -
-
-
- {% if title %} -

{{ title }}

- {% endif %} - {% if description %} -

- {{ description }} -

- {% endif %} - {{ content }} -
-
-
-
- {% include scripts.html %} - - diff --git a/docs/_includes/layouts/page.html b/docs/_includes/layouts/page.html index b1e67484e1..8322edebf8 100644 --- a/docs/_includes/layouts/page.html +++ b/docs/_includes/layouts/page.html @@ -3,28 +3,30 @@ {% include head.html %} - {% include darkmode.html %} + {% include theme.html %} {% include header.html %} -
+
{% include navigation.html %} -
-
-
-
Sections
- {{ content | toc | safe }} +
+ {% if menu %} +
+
+
Sections
+ {{ content | toc | safe }} +
-
+ {% endif %} {% comment %} - This container’s .fl1 doesn't behave properly unless we add an explicit width. + This container’s .fl-grow1 doesn't behave properly unless we add an explicit width. https://stackoverflow.com/questions/38723559/flex-item-exceeds-its-container {% endcomment %} -
+
{% if js %} -
-

{{ title }}

- +
+

{{ title }}

+
{% icon "Checkmark" %}
javascript
@@ -38,9 +40,50 @@

{{ title }}

{% endif %} {{ content }} + +
+
+
+ +
+ +
+ +
+
+ +
+ + + + + +
+
+ + {% include scripts.html %} diff --git a/docs/_includes/markdown-prose.md b/docs/_includes/markdown-prose.md index 721ce98ca9..bd8dac3e1d 100644 --- a/docs/_includes/markdown-prose.md +++ b/docs/_includes/markdown-prose.md @@ -183,7 +183,7 @@ We also need to make sure inline code looks good, like if I wanted to talk about ### Sometimes I even use `code` in headings -Another thing I’ve done in the past is put a `code` tag inside of a link, like if I wanted to tell you about the [`stackexchange/stacks`](https://github.com/stackexchange/stacks) repository. I don’t love that there is an underline below the backticks but it is absolutely not worth the madness it would require to avoid it. +Another thing I’ve done in the past is put a `code` tag inside of a link, like if I wanted to tell you about the [`stackexchange/stacks`](https://github.com/stackexchange/stacks) repository. ### We still need to think about stacked headings though. @@ -191,6 +191,11 @@ Another thing I’ve done in the past is put a `code` tag inside of a link, like Phew, with any luck we have styled the headings above this text and they look pretty good. +##### We should also make sure we're styling `h5` elements as well. + Let’s add a closing paragraph here so things end with a decently sized block of text. I can’t explain why I want things to end that way but I have to assume it’s because I think things will look weird or unbalanced if there is a heading too close to the end of the document. +###### And, finally, an `h6`. +Ultimately, though, we also want to support the `h6` headers. + What I’ve written here is probably long enough, but adding this final sentence can’t hurt. \ No newline at end of file diff --git a/docs/_includes/navigation.html b/docs/_includes/navigation.html index 9c0eaaf87c..92089e2226 100755 --- a/docs/_includes/navigation.html +++ b/docs/_includes/navigation.html @@ -1,7 +1,7 @@ -
-
+
+
-
+
{% if site-navigation %} {% endif %} - -
- - {% icon "LogoGlyphSm" %} - - - - {% icon "GitHub", "", "24" %} - - - - - - - -
diff --git a/docs/_includes/notice-email-head-support.html b/docs/_includes/notice-email-head-support.html index 1323410707..3712e74955 100644 --- a/docs/_includes/notice-email-head-support.html +++ b/docs/_includes/notice-email-head-support.html @@ -1,6 +1,3 @@ -
-
{% icon "Alert" %}
-
- Note: Only email clients that support <style> in <head> will render this. -
-
\ No newline at end of file +{% tip "", "", "ai-center sm:ai-start" %} + Note: Only email clients that support <style> in <head> will render this. +{% endtip %} \ No newline at end of file diff --git a/docs/_includes/notice-email-main-templates.html b/docs/_includes/notice-email-main-templates.html index 3d1cf5790e..b36f6195cc 100644 --- a/docs/_includes/notice-email-main-templates.html +++ b/docs/_includes/notice-email-main-templates.html @@ -1,7 +1,4 @@ -
-
{% icon "Alert" %}
-
-

Note: These templates are in Iterable and Hubspot. The code here can also be copied and pasted.

-

Emails in our codebase use a main template (eg. _Stacks-Layout.Html.cshtml) that includes the <head>, logo, and footer. Only the middle part of these templates are needed (between <!-- EMAIL BODY : BEGIN --> and <!-- EMAIL BODY : END --> code comments).

-
-
\ No newline at end of file +{% tip %} +

Note: These templates are in Iterable and Hubspot. The code here can also be copied and pasted.

+

Emails in our codebase use a main template (eg. _Stacks-Layout.Html.cshtml) that includes the <head>, logo, and footer. Only the middle part of these templates are needed (between <!-- EMAIL BODY : BEGIN --> and <!-- EMAIL BODY : END --> code comments).

+{% endtip %} \ No newline at end of file diff --git a/docs/_includes/scripts.html b/docs/_includes/scripts.html index 9fd1c5bf5e..847719fff1 100644 --- a/docs/_includes/scripts.html +++ b/docs/_includes/scripts.html @@ -1,13 +1,14 @@ - - - + + + + - + - \ No newline at end of file + \ No newline at end of file diff --git a/docs/_includes/darkmode.html b/docs/_includes/theme.html similarity index 59% rename from docs/_includes/darkmode.html rename to docs/_includes/theme.html index f65f03c521..0ea57d40ae 100755 --- a/docs/_includes/darkmode.html +++ b/docs/_includes/theme.html @@ -4,6 +4,7 @@ \ No newline at end of file + diff --git a/docs/_includes/toast-clipboard.html b/docs/_includes/toast-clipboard.html new file mode 100644 index 0000000000..ef7daf3c65 --- /dev/null +++ b/docs/_includes/toast-clipboard.html @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/docs/assets/img/illustration-crane-dark.svg b/docs/assets/img/illustration-crane-dark.svg deleted file mode 100644 index b17b013bab..0000000000 --- a/docs/assets/img/illustration-crane-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/assets/img/illustration-crane.svg b/docs/assets/img/illustration-crane.svg deleted file mode 100644 index d5b6e2b9d6..0000000000 --- a/docs/assets/img/illustration-crane.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/assets/img/illustration-field-dark.svg b/docs/assets/img/illustration-field-dark.svg deleted file mode 100644 index 54c557d6cc..0000000000 --- a/docs/assets/img/illustration-field-dark.svg +++ /dev/null @@ -1 +0,0 @@ -Artboard 4 \ No newline at end of file diff --git a/docs/assets/img/illustration-field.svg b/docs/assets/img/illustration-field.svg deleted file mode 100644 index 41c54b26cd..0000000000 --- a/docs/assets/img/illustration-field.svg +++ /dev/null @@ -1 +0,0 @@ -Artboard 4 \ No newline at end of file diff --git a/docs/assets/img/logos/collectives/collectives-logo-compact.png b/docs/assets/img/logos/collectives/collectives-logo-compact.png new file mode 100644 index 0000000000..b73b71bb69 Binary files /dev/null and b/docs/assets/img/logos/collectives/collectives-logo-compact.png differ diff --git a/docs/assets/img/logos/collectives/collectives-logo-compact.svg b/docs/assets/img/logos/collectives/collectives-logo-compact.svg new file mode 100644 index 0000000000..fd7f33460e --- /dev/null +++ b/docs/assets/img/logos/collectives/collectives-logo-compact.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/img/logos/collectives/collectives-logo.png b/docs/assets/img/logos/collectives/collectives-logo.png new file mode 100644 index 0000000000..8cc1f46b26 Binary files /dev/null and b/docs/assets/img/logos/collectives/collectives-logo.png differ diff --git a/docs/assets/img/logos/collectives/collectives-logo.svg b/docs/assets/img/logos/collectives/collectives-logo.svg new file mode 100644 index 0000000000..48f87c403c --- /dev/null +++ b/docs/assets/img/logos/collectives/collectives-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/img/placeholder.svg b/docs/assets/img/placeholder.svg new file mode 100644 index 0000000000..0ffe820c47 --- /dev/null +++ b/docs/assets/img/placeholder.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/docs/assets/img/video-thumbnail.png b/docs/assets/img/video-thumbnail.png new file mode 100644 index 0000000000..2ec540c7a3 Binary files /dev/null and b/docs/assets/img/video-thumbnail.png differ diff --git a/docs/assets/js/clipboard.js b/docs/assets/js/clipboard.js new file mode 100644 index 0000000000..c77299f0a0 --- /dev/null +++ b/docs/assets/js/clipboard.js @@ -0,0 +1,27 @@ +var copyButtons = document.querySelectorAll('.js-clipboard'); +var copyNotice = document.querySelector('.js-clipboard-toast'); + +for (var button of copyButtons) { + button.addEventListener('click', copyToClipboard) +} + +function copyToClipboard(evt) { + var target = evt.currentTarget; + var selection = window.getSelection(); + var range = document.createRange(); + + // Grad the text + range.selectNodeContents(target); + selection.removeAllRanges(); + selection.addRange(range); + + // Copy to clipboard + document.execCommand('copy'); + selection.removeAllRanges(); + + // Open a toaster + copyNotice.setAttribute("aria-hidden", "false"); + setTimeout(function () { + copyNotice.setAttribute("aria-hidden", "true"); + }, 3000); +} \ No newline at end of file diff --git a/docs/assets/js/feature.darkmode.js b/docs/assets/js/feature.darkmode.js deleted file mode 100644 index d7421fe43c..0000000000 --- a/docs/assets/js/feature.darkmode.js +++ /dev/null @@ -1,26 +0,0 @@ -$(document).ready(function () { - var darkModeBtn = $(".js-darkmode-btn"); - var body = $("body"); - - darkModeBtn.click(function (e) { - e.preventDefault(); - e.stopPropagation(); - - var browserPrefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; - - var isForcedDarkMode = body.hasClass("theme-dark"); - var isUnforcedDarkMode = browserPrefersDark && body.hasClass("theme-system"); - - if (browserPrefersDark) { - body.toggleClass("theme-system", !isUnforcedDarkMode); - body.toggleClass("theme-dark", false); - } else { - body.toggleClass("theme-system", true); - body.toggleClass("theme-dark", !isForcedDarkMode); - } - - localStorage.setItem("forceDarkModeOn", !(isUnforcedDarkMode || isForcedDarkMode)); - - return false; - }); -}); diff --git a/docs/assets/js/feature.modals.js b/docs/assets/js/feature.modals.js new file mode 100644 index 0000000000..6fda6f0455 --- /dev/null +++ b/docs/assets/js/feature.modals.js @@ -0,0 +1,17 @@ +(function() { + document.querySelectorAll(".js-modal-open").forEach(function(el) { + el.addEventListener("click", function(e) { + e.stopPropagation(); + e.preventDefault(); + var targetSelector = el.dataset.target; + Stacks.showModal(document.querySelector(targetSelector)); + }); + }); + + document.querySelectorAll(".js-modal-close").forEach(function(el) { + el.addEventListener("click", function(e) { + e.stopPropagation(); + e.preventDefault(); + }); + }); +}()); \ No newline at end of file diff --git a/docs/assets/js/feature.popovers.js b/docs/assets/js/feature.popovers.js index 05fb679436..c4d74994d0 100644 --- a/docs/assets/js/feature.popovers.js +++ b/docs/assets/js/feature.popovers.js @@ -1,4 +1,21 @@ $(document).ready(function() { Stacks.setTooltipText(document.querySelector(".js-text-tooltip-example"), "Only members of this Team can see the information posted here. It will never be shared publicly or accessible outside of your Team.", { placement: "top-start" }); Stacks.setTooltipHtml(document.querySelector(".js-html-tooltip-example"), "View all questions with stacks", { placement: "top-end" }); -}); \ No newline at end of file + + Stacks.addController("section", { + targets: ["help"], + showHelp(e) { Stacks.showPopover(this.helpTarget); e.stopPropagation(); }, + hideHelp(e) { Stacks.hidePopover(this.helpTarget); }, + }); + + Stacks.addController("actions", { + loaded: false, + load() { + if (this.loaded) { return; } + setTimeout(() => { + Stacks.attachPopover(this.element, `
`, { autoShow: true, toggleOnClick: true, placement: "bottom" }); + this.loaded = true; + }); + }, + }); +}); diff --git a/docs/assets/js/feature.theming.js b/docs/assets/js/feature.theming.js new file mode 100644 index 0000000000..774536da0f --- /dev/null +++ b/docs/assets/js/feature.theming.js @@ -0,0 +1,64 @@ +$(document).ready(function () { + var themeDarkToggleSwitch = $("#toggle-theme-dark"); + var themeCustomToggleSwitch = $("#toggle-theme-custom"); + var themeHighcontrastToggleSwitch = $("#toggle-theme-highcontrast"); + var body = $("body"); + var browserPrefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches; + var isCustom = body.hasClass("theme-custom"); + var isDark = body.hasClass("theme-dark") || browserPrefersDark && body.hasClass("theme-system"); + var isHighcontrast = body.hasClass("theme-highcontrast"); + + themeCustomToggleSwitch.prop("checked", isCustom); + themeDarkToggleSwitch.prop("checked", isDark); + themeHighcontrastToggleSwitch.prop("checked", isHighcontrast); + + themeDarkToggleSwitch.change(function (e) { + e.preventDefault(); + e.stopPropagation(); + + var isForcedDarkMode = body.hasClass("theme-dark"); + var isUnforcedDarkMode = browserPrefersDark && body.hasClass("theme-system"); + + if (browserPrefersDark) { + body.toggleClass("theme-system", !isUnforcedDarkMode); + body.toggleClass("theme-dark", false); + } else { + body.toggleClass("theme-system", true); + body.toggleClass("theme-dark", !isForcedDarkMode); + } + + $(this).prop("checked", !(isUnforcedDarkMode || isForcedDarkMode)); + + localStorage.setItem("forceDarkModeOn", !(isUnforcedDarkMode || isForcedDarkMode)); + + return false; + }); + + themeCustomToggleSwitch.change(function (e) { + e.preventDefault(); + e.stopPropagation(); + + var isCustom = body.hasClass("theme-custom"); + + $(this).prop("checked", !isCustom); + body.toggleClass("theme-custom", !isCustom); + + localStorage.setItem("customTheme", !isCustom); + + return false; + }); + + themeHighcontrastToggleSwitch.change(function (e) { + e.preventDefault(); + e.stopPropagation(); + + var isHighcontrast = body.hasClass("theme-highcontrast"); + + $(this).prop("checked", !isHighcontrast); + body.toggleClass("theme-highcontrast", !isHighcontrast); + + localStorage.setItem("forceHighContrastModeOn", !isHighcontrast); + + return false; + }); +}); diff --git a/docs/assets/js/feature.topbar.js b/docs/assets/js/feature.topbar.js new file mode 100644 index 0000000000..0795f92c62 --- /dev/null +++ b/docs/assets/js/feature.topbar.js @@ -0,0 +1,13 @@ +$(".js-topbar-example .js-search-button").on("click", function() { + $(this).closest(".s-topbar") + .find(".s-topbar--searchbar") + .toggleClass("s-topbar--searchbar__open"); +}); + +$(".js-topbar-example .s-topbar--menu-btn").on("click", function() { + $(this).toggleClass("is-selected"); +}); + +$(".js-topbar-example .s-topbar--notice").on("click", function() { + $(this).toggleClass("is-unread"); +}); \ No newline at end of file diff --git a/docs/assets/js/feedback.js b/docs/assets/js/feedback.js new file mode 100755 index 0000000000..3ba8456ede --- /dev/null +++ b/docs/assets/js/feedback.js @@ -0,0 +1,35 @@ +var feedbackForms = document.querySelectorAll('.js-feedback-form'); +var feedbackToast = document.querySelector('.js-feedback-toast'); + +for (var form of feedbackForms) { + form.addEventListener('submit', handleFeedback) +} + +function handleFeedback(evt) { + evt.preventDefault(); + + var formData = new FormData(evt.target); + fetch('/', { + method: 'POST', + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: new URLSearchParams(formData).toString() + }) + .then(() => openToast()) + .catch((error) => alert(error)) +} + +function openToast() { + feedbackToast.setAttribute("aria-hidden", "false"); + + for (var form of feedbackForms) { + form.classList.add("pe-none", "o50"); + } + + setTimeout(function () { + feedbackToast.setAttribute("aria-hidden", "true"); + + for (var form of feedbackForms) { + form.classList.remove("pe-none", "o50"); + } + }, 5000); +} \ No newline at end of file diff --git a/docs/assets/js/hamburger.js b/docs/assets/js/hamburger.js index f716cab907..694ea1eef9 100644 --- a/docs/assets/js/hamburger.js +++ b/docs/assets/js/hamburger.js @@ -1,15 +1,12 @@ $(document).ready(function() { var navigation = $(".js-navigation"); - var closeIcon = $(".js-hamburger-close-icon"); - var hamburgerIcon = $(".js-hamburger-icon"); var hamburgerBtn = $(".js-hamburger-btn"); - hamburgerBtn.click(function(e) { + hamburgerBtn.on("click", function(e) { e.preventDefault(); e.stopPropagation(); - hamburgerIcon.toggleClass("d-none"); - closeIcon.toggleClass("d-none"); + hamburgerBtn.toggleClass("is-selected"); navigation.toggleClass("md:d-none"); }); }); diff --git a/docs/assets/js/navigation.js b/docs/assets/js/navigation.js index e99624ea41..1c912936f5 100644 --- a/docs/assets/js/navigation.js +++ b/docs/assets/js/navigation.js @@ -1,18 +1,30 @@ $(document).ready(function() { // Cache some variables var navigation = $(".js-navigation"); - var closeIcon = $(".js-hamburger-close-icon"); - var hamburgerIcon = $(".js-hamburger-icon"); + var hamburgerBtn = $(".js-hamburger-btn"); + + // Disable any empty links + $("a[href='#']").click(function(e) { + e.preventDefault(); + }); function regenerateMenu () { // Hide the navigation if we've opened it - hamburgerIcon.removeClass("d-none"); - closeIcon.addClass("d-none"); + hamburgerBtn.removeClass("is-selected"); navigation.addClass("md:d-none"); } + function killEmptyLinks() { + // Kill default behavior on empty links + $("a[href='#']").on("click", function(e) { + e.preventDefault(); + e.stopPropagation(); + }); + } + $.when($.ready).then(function() { regenerateMenu(); + killEmptyLinks(); window.history.replaceState({ 'href': window.location.href, @@ -24,7 +36,7 @@ $(document).ready(function() { $('#nav').on('click', 'a', function (event) { // Allow opening links in new tabs - if (event.metaKey) { + if (event.metaKey || event.ctrlKey) { return } @@ -56,6 +68,7 @@ $(document).ready(function() { $(document).scrollTop(0) regenerateMenu(); + killEmptyLinks(); // Add page load to browser history window.history.pushState({ diff --git a/docs/assets/js/search.js b/docs/assets/js/search.js index 7b48036d81..ec79e997db 100755 --- a/docs/assets/js/search.js +++ b/docs/assets/js/search.js @@ -5,20 +5,11 @@ $(document).ready(function() { inputSelector: '#searchbox' }); - // Kill default behavior on empty links - $("a[href='#']").on("click", function(e) { - e.preventDefault(); - e.stopPropagation(); - }); - // Show or hide search - var searchBar = $(".js-stacks-search-bar"); var searchContainer = $(".js-search"); var searchCloseIcon = $(".js-search-close-icon"); var searchIcon = $(".js-search-icon"); var searchBtn = $(".js-search-btn"); - var hamburgerBtn = $(".js-hamburger-btn"); - var logo = $(".js-logo"); searchBtn.click(function(e) { e.preventDefault(); @@ -26,12 +17,10 @@ $(document).ready(function() { searchIcon.toggleClass("d-none"); searchCloseIcon.toggleClass("d-none"); - searchContainer.toggleClass("sm:d-none"); - hamburgerBtn.toggleClass("md:d-block"); - logo.toggleClass("sm:d-none"); + searchContainer.toggleClass("s-topbar--searchbar__open"); - if ( searchIcon.hasClass("d-none") ) { - searchBar.focus(); + if (searchContainer.hasClass("s-topbar--searchbar__open") ) { + searchContainer.find("input").focus(); } }); }); diff --git a/docs/assets/less/stacks-documentation.less b/docs/assets/less/stacks-documentation.less index b59a79d0af..acff8723dd 100644 --- a/docs/assets/less/stacks-documentation.less +++ b/docs/assets/less/stacks-documentation.less @@ -22,14 +22,20 @@ margin-bottom: 0.75em; } -.stacks-intro { - background-image: url("../img/illustration-crane.svg"), url("../img/illustration-field.svg"); - background-position: top -35% left 15%, bottom 10% right 8%; - background-repeat: no-repeat, no-repeat; +.stacks-intro-crane { + position: absolute; + top: -15%; + left: 17%; +} - .dark-mode({ - background-image: url("../img/illustration-crane-dark.svg"), url("../img/illustration-field-dark.svg"); - }); +.stacks-intro-field { + position: absolute; + bottom: 5%; + right: 9%; +} + +.stacks-topbar.s-topbar .s-topbar--content { + --theme-topbar-item-color: var(--black-300); } .stacks-home-nav { @@ -37,9 +43,28 @@ } #stacks-internals #screen-md({ - .stacks-intro { - background-position: top -15% left 15%, bottom 10% right 8%; - background-size: 135px 327px, 537px 390px; + .stacks-intro-crane { + width: 135px; + height: 327px; + top: -8%; + left: 12%; + } + + .stacks-intro-field { + width: 537px; + height: 390px; + } +}, @force-selector: true); + +#stacks-internals #screen-md({ + .stacks-navigation-shadow { + box-shadow: 3px 0 3px 0 hsla(0, 0, 0, 0.02), 7px 0 6px 0 hsla(0, 0, 0, 0.03), 13px 0 11px 0 hsla(0, 0, 0, 0.04), 22px 0 20px 0 hsla(0, 0, 0, 0.04), 42px 0 37px 0 hsla(0, 0, 0, 0.05); + } +}, @force-selector: true); + +#stacks-internals #screen-sm({ + .stacks-navigation-shadow { + box-shadow: none; } }, @force-selector: true); @@ -47,28 +72,37 @@ .stacks-home-nav { margin-bottom: 170px; } - .stacks-intro { - background-position: top 0 left 15%, bottom 20% right 8%; - background-size: 90px 218px, 358px 260px; + + .stacks-intro-crane { + width: 90px; + height: 218px; + + top: 0; + left: 12%; + } + + .stacks-intro-field { + width: 358px; + height: 260px; + bottom: 20%; } }, @force-selector: true); -@media ( max-width:320px ) { +@media (max-width: 320px) { html .stacks-home-nav { margin-bottom: 230px; } - html .stacks-intro { + + html .stacks-intro-crane { background-position: top 0 left 15%, bottom 50% right 0; background-size: 69px 166px, 272px 197px; } -} -// $$ 404 -// ---------------------------------------------------------------------------- -.stacks-404 { - background-image: url("../img/illustration-astronaut.svg"); - background-position: 15% 15%; - background-repeat: no-repeat; + html .stacks-intro-field { + width: 272px; + height: 197px; + bottom: 33%; + } } // $$ BACKGROUNDS EXAMPLE @@ -82,7 +116,7 @@ .toc { ol { .list-reset; - .grid; + .d-flex; .fd-column; li { @@ -117,7 +151,7 @@ // $$ TITLES // ---------------------------------------------------------------------------- .stacks-title { - text-shadow: 0 0 10px var(--orange-400), 0 0 10px var(--orange-400), 0 0 10px var(--orange-400); + text-shadow: 0 0 10px var(--theme-primary-400), 0 0 10px var(--theme-primary-400), 0 0 10px var(--theme-primary-400); text-rendering: optimizeLegibility; } @@ -126,7 +160,7 @@ .stacks-h3, .stacks-h4 { margin-bottom: 0; - font-weight: 700; + font-weight: 600; line-height: @lh-sm; color: var(--fc-dark); text-rendering: optimizeLegibility; @@ -188,18 +222,12 @@ padding: 3px 5px @su2 @su4; border-radius: @br-sm; background-color: var(--black-075); - font-size: @fs-caption; - font-family: @ff-mono; + font-family: var(--ff-mono); color: var(--fc-dark); line-height: @lh-xs; - vertical-align: middle; - white-space: nowrap; overflow-wrap: break-word; -} - -.stacks-code { white-space: normal; } @@ -223,13 +251,17 @@ border-radius: @br-md; box-shadow: var(--bs-sm); + .highcontrast-mode({ + box-shadow: none; + }); + > pre.s-code-block { border-radius: @br-md @br-md 0 0; - border: 1px solid var(--black-100); + border: 1px solid var(--bc-medium); max-height: 24rem; .dark-mode({ - border-color: transparent; + border-color: var(--bc-lighter); }); } @@ -243,12 +275,12 @@ padding: @su16; border-bottom-left-radius: @br-md; border-bottom-right-radius: @br-md; - border: 1px solid var(--black-100); + border: 1px solid var(--bc-medium); border-top-width: 0; font-size: @fs-body1; .dark-mode({ - border-color: transparent; + border-color: var(--bc-lighter); background: var(--black-025); }); } @@ -275,6 +307,10 @@ background-color: var(--black-025); box-shadow: inset 0 -1px 0 var(--black-075); color: var(--fc-medium); + + .dark-mode({ + fill: var(--black); + }); } // ============================================================================ @@ -282,21 +318,15 @@ // Used to showcase grid layouts and cells // ---------------------------------------------------------------------------- -.stacks-grid-example--cell { +.stacks-flex-example--item { padding: @su8; - border: 1px solid var(--black-100); + border: 1px solid var(--bc-medium); background-color: var(--black-075); - font-family: @ff-mono; + font-family: var(--ff-mono); font-size: @fs-caption; color: var(--fc-dark); } -.stacks-grid-example { - display: flex; - .grid__center; - height: 100%; -} - // ============================================================================ // $ COLORS // ---------------------------------------------------------------------------- @@ -313,16 +343,16 @@ width: 100% !important; [class^="ds-dataset-"] { - .algolia-docsearch-suggestion--text { - .algolia-docsearch-suggestion--highlight { - box-shadow: inset 0 -2px 0 0 rgba(68, 168, 179,.8); - } - } - .algolia-docsearch-suggestion--highlight { color: var(--fc-medium); background: var(--orange-100); } + + .algolia-docsearch-suggestion--text { + .algolia-docsearch-suggestion--highlight { + box-shadow: inset 0 -2px 0 0 hsla(186, 45%, 48%, 0.8); + } + } } .ds-dropdown-menu { @@ -346,7 +376,7 @@ overflow: visible !important; color: inherit !important; text-indent: 0 !important; - background: 0 0 !important + background: 0 0 !important; } @media (max-width: 640px) { @@ -366,29 +396,85 @@ } // ============================================================================ -// $ Homepage grid +// $ Theming UI // ---------------------------------------------------------------------------- +.stacks-theme-button { + color: var(--black-300); + position: relative; + padding-right: @su24 !important; + + &:after { + content: ""; + position: absolute; + z-index: @zi-active; + top: calc(50% - 2px); + right: @su12 - @su2; + border-style: solid; + border-width: @su4; + border-top-width: @su4; + border-bottom-width: 0; + border-color: currentColor transparent; + pointer-events: none; + } -.stacks-grid { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; - grid-column-gap: @su16; - grid-row-gap: @su16; -} - -@media ( max-width:1200px ) { - .stacks-grid { - grid-template-columns: 1fr 1fr; + &.is-selected { + color: var(--black-600); } -} -@media ( max-width:530px ) { - .stacks-grid { - grid-template-columns: 1fr; + &.stacks-theme-button__home { + color: var(--white); + + &.is-selected { + color: var(--white); + } } } +.theme-custom { + --theme-base-primary-color-h: 172; + --theme-base-primary-color-s: 37%; + --theme-base-primary-color-l: 48%; + --theme-base-primary-color-r: 77; + --theme-base-primary-color-g: 168; + --theme-base-primary-color-b: 156; + --theme-base-secondary-color-h: 259; + --theme-base-secondary-color-s: 29%; + --theme-base-secondary-color-l: 55%; + --theme-base-secondary-color-r: 129; + --theme-base-secondary-color-g: 108; + --theme-base-secondary-color-b: 174; +} .team-avatar { background-image: url("../img/team-avatar.png"); } + +// ============================================================================ +// $ Highlighting +// ---------------------------------------------------------------------------- +#stacks-internals #screen-lg({ + .lg\:highlight { + padding: 3px 8px; + background-color: var(--highlight-variable); + border-radius: 40px; + color: var(--highlight-bg); + } +}); + +#stacks-internals #screen-md({ + .md\:highlight { + padding: 3px 8px; + background-color: var(--highlight-variable); + border-radius: 40px; + color: var(--highlight-bg); + } +}); + +#stacks-internals #screen-sm({ + .sm\:highlight { + padding: 3px 8px; + background-color: var(--highlight-variable); + border-radius: 40px; + color: var(--highlight-bg); + } +}); diff --git a/docs/brand/colors.html b/docs/brand/colors.html new file mode 100644 index 0000000000..683b4e1463 --- /dev/null +++ b/docs/brand/colors.html @@ -0,0 +1,156 @@ +--- +layout: page +title: Colors +description: See the Product section for colors when building with Stacks. While there is some cross-over with the Product colors, using Stacks color classes will mean they adjust depending on context (e.g., dark mode) +--- + + + +
+ {% header "h2", "Primary" %} +
+
+
+
+

Orange

+
+ Hex + #F48024 +
+
+ Pantone + Orange 021 U +
+
+ Stacks + orange-400 +
+
+
+
+
+
+

Black

+
+ Hex + #242729 +
+
+ Pantone + Black 6 U +
+
+ Stacks + black-800 +
+
+
+
+
+
+

Gray

+
+ Hex + #BBC0C4 +
+
+ Pantone + 442 U +
+
+ Stacks + black-200 +
+
+
+
+
+ +
+ {% header "h2", "Secondary" %} +
+
+
+
+

Blue

+
+ Hex + #0095FF +
+
+ Pantone + 2995 U +
+
+ Stacks + blue-500 +
+
+
+
+
+
+

Yellow

+
+ Hex + #FFB500 +
+
+ Pantone + 109 U +
+
+ Stacks + n/a +
+
+
+
+
+ +
+ {% header "h2", "Verticals" %} +
+
+
+
+

Teams Purple

+
+ Hex + #2B2D6E +
+
+ Pantone + 2105 U +
+
+ Stacks + n/a +
+
+
+
+
+
+

Advertising Blue

+
+ Hex + #075EC3 +
+
+ Pantone + 2935 U +
+
+ Stacks + n/a +
+
+
+
+
+ + + + +{% include toast-clipboard.html %} \ No newline at end of file diff --git a/docs/brand/copywriting/naming.html b/docs/brand/copywriting/naming.html new file mode 100644 index 0000000000..52bc7514c3 --- /dev/null +++ b/docs/brand/copywriting/naming.html @@ -0,0 +1,259 @@ +--- +layout: page +title: Naming guidelines +description: Quick guidelines for using Stack Overflow and our product names. +--- + +
+ {% header "h2", "Stack Overflow" %} + + + + + + + + + + + + + + + + + +
{% icon "Clear", "mtn1 mbn1" %} Incorrect{% icon "Checkmark", "mtn1 mbn1" %} Correct
StackoverflowStack Overflow
stackoverflow
StackOverflow
+ + {% header "h2", "Stack Overflow for Teams" %} + + + + + + + + + + + + + + + + + + + + +
{% icon "Clear", "mtn1 mbn1" %} Incorrect{% icon "Checkmark", "mtn1 mbn1" %} Correct
Stack Overflow TeamsStack Overflow for Teams
Teams
Stack Overflow for Business
Stack Overflow for Enterprise
+ + {% header "h3", "Specific plans" %} + + {% header "h4", "Do" %} + +
    +
  • Use “Free, Basic, Business, Enterprise” once you’re talking about specifics.
  • +
  • Use ‘Private Q&A’ as a descriptor to refer to our product suite on stackoverflow.com or with an audience that we’re certain is aware of our special sauces – our Q&A format.
  • +
  • Once discussing in-depth, use the terms: Stack Overflow for Teams, Stack Overflow Business, Stack Overflow Enterprise. Note: we won’t reference the base tier as Stack Overflow Basic.
  • +
+ + {% header "h4", "Don’t" %} + +
    +
  • Don’t use “for” when referencing each tier. It is simply Free, Basic, Business, and Enterprise
  • +
  • Don’t append Free, Basic, Business, or Enterprise to the end of Stack Overflow for Teams
  • +
  • Don’t use ‘Private Q&A’ when referring to our product suite for marketing and promotional efforts outside of our core stackoverflow.com audience.
  • +
+ + {% header "h2", "Collectives on Stack Overflow" %} + + {% header "h3", "Capitalization" %} + + {% header "h4", "Headers, subheaders, and tabs" %} + +
    +
  • Do follow the capitalization rules for headers, sub-headers, and menu tabs.
  • +
  • Use sentence case for all headings (Sentence case involves capitalizing the first word, first word of a subtitle, and all proper nouns.)
  • +
  • Capitalize the first word of a heading
  • +
  • Capitalize proper or trademarked nouns (names of products, people, or specific companies) +
  • Lowercase for everything else
  • +
+ + + + + + + + + + + + +
{% icon "Clear", "mtn1 mbn1" %} Don’t{% icon "Checkmark", "mtn1 mbn1" %} Do
User RolesUser roles
+ + {% header "h4", "Product and feature names" %} + +

+ If a product or feature isn’t unique to Stack Overflow, don’t capitalize it (blogs, pages, etc.) If it is unique to Stack Overflow as its own product, do capitalize it. +

+ + + + + + + + + + + + +
{% icon "Clear", "mtn1 mbn1" %} Don’t{% icon "Checkmark", "mtn1 mbn1" %} Do
As soon as it’s ready, put your Blog Post upAs soon as it’s ready, put your blog post up
+ + {% header "h3", "Specific products and features " %} + + {% header "h4", "Trade Mark" %} + +
    +
  • We have trademarked “Collectives™ on Stack Overflow”.
  • +
  • Apply the trademark ™ symbol to the first instance of “Collectives™ on Stack Overflow” in a document, communication, or marketing materials/assets.
  • +
  • If there is a headline/title slide, use the symbol in the first instance of the product name in the body copy of your document, in addition to using the ™ in the headline/title.
  • +
  • Where possible, use the unicode character for trade mark:
  • +
+ + + + + + + + + + + + + + + +
{% icon "Clear", "mtn1 mbn1" %} Don’t{% icon "Checkmark", "mtn1 mbn1" %} Do
<sup>TM</sup>
TM
+ + {% header "h4", "…on Stack Overflow" %} + +
    +
  • Use … “on Stack Overflow” sparingly.
  • +
  • Don’t use “…on Stack Overflow” unless there’s a lack of surrounding context and we need the audience to know it’s associated with Stack Overflow.
  • +
  • Adding “…on Stack Overflow” doesn’t add clarity in the context of other Stack Overflow products and features.
  • +
+ + + + + + + + + + + + + + + + +
{% icon "Checkmark", "mtn1 mbn1" %} When to use “on Stack Overflow”
You’re writing “Collectives™ on Stack Overflow” for the first time on a page
When it should be differentiated from other external products or features
When it needs to be associated with Stack Overflow
+ + {% header "h4", "Collectives vs. collectives" %} + +

When do you capitalize the C in “Collective(s)”?

+ +
    +
  • Always capitalize “Collectives” and “Collective” when you are using them as proper nouns.
  • +
  • If you’re just generally referring to a collective, even if it comes right after a company name, it will always be lowercase. +
      +
    • We can see in Audiobubble’s collective that there are…
    • +
    • Google Cloud has a collective for its biggest advocates…
    • +
    +
  • +
  • Even if you’re putting “Join a collective” on a button or in a headline, it will be lowercase unless it is directly following the name of a company.
  • +
+ + + + + + + + + + + + + + + + + + + + +
{% icon "Clear", "mtn1 mbn1" %} Don’t{% icon "Checkmark", "mtn1 mbn1" %} Do
join the Google Cloud collectivejoin the Google Cloud Collective
join an Collectivejoin a collective
A company’s Collective page will be located at the top right of the screenA company’s collective page will be located at the top right of the screen
+ + {% header "h4", "Articles vs. articles" %} + +
    +
  • This can be confusing, because we have a feature called “Articles,” under which you may write a how-to guide, or an announcement, or indeed, an article. So this one depends on the context.
  • +
  • If you’re referring to a generic article, it’s lowercase.
  • +
  • When in doubt, ask, “Is this referring to the specific website section (Articles), or to the thing (articles)?”
  • +
  • If you’re talking about the Articles section of your collective on Stack Overflow, you’ll call it “Articles.”
  • +
+ + + + + + + + + + + + + + + + + + + + + + + + +
{% icon "Clear", "mtn1 mbn1" %} Don’t{% icon "Checkmark", "mtn1 mbn1" %} Do
I’m writing an article and then I’m going to put it in our team’s articles sectionI’m writing an article and then I’m going to put it in our team’s Articles section
In articles, you can find how-to guides, blog posts, and articlesIn Articles, you can find how-to guides, blog posts, and articles
Create articlesCreate Articles
Pinned articlesPinned Articles
+ + {% header "h4", "User roles" %} + +

+ Capitalize user roles, no matter where they are and in what context. +

+ + + + + + + + + + + + + + + + +
{% icon "Clear", "mtn1 mbn1" %} Don’t{% icon "Checkmark", "mtn1 mbn1" %} Do
employeesEmployees
Recommended membersRecommended Members
+
\ No newline at end of file diff --git a/docs/brand/data-visualization.html b/docs/brand/data-visualization.html new file mode 100644 index 0000000000..7d09e37cc4 --- /dev/null +++ b/docs/brand/data-visualization.html @@ -0,0 +1,268 @@ +--- +layout: page +title: Data visualization +description: Tell a story with data visualizations. Use this section for guidance and examples. +--- + +
+ {% header "h2", "Guidelines" %} +

Why use data visualization? Charts, graphs, and visuals draw attention to the data. While raw data can be hard to understand, data visualization presents a compelling story that answers a specific question and can inspire action. When presenting data through visualizations, keep the following principles in mind:

+ + {% header "h3", "Focus" %} +

Designs should immediately draw the viewer’s eye to the most important information. That’s why the most important data should have the highest contrast. As you design, consider how much attention the data warrants—is it the main focus or just a supporting asset?

+ + {% header "h3", "Explicit" %} +

Designs should be easy to understand and accessible to all. Always use real data that’s represented accurately. Consider what range your data set has and how it will scale with more or fewer data points.

+ + {% header "h3", "Purpose" %} +

Don’t add extraneous data or ornamentation. Answer a single question with clear and accurate information. What’s the story you’re trying to tell?

+
+ +
+ {% header "h2", "Chart types" %} +

There are many types of charts and graphs, so when you’re designing one, think first about its function. For example: are you comparing something? Or are you highlighting a trend over a long period of time? Below, we’ve grouped several types of charts according to their recommended functions (You’ll see some types in multiple groups). Before you start designing, determine what you’d like to communicate to your audience, and use that to guide you in selecting the appropriate chart or graph type.

+ + {% header "h3", "Comparison" %} +

This is the most common type of chart. Compare two or more values within two different parameters as the framework. This chart type helps to show differences/similarities between items and give context to the impact of those differences/similarities.

+ +
+
+ +
Bar chart
+
+
+ +
Bubble chart
+
+
+ +
Radar chart
+
+
+ +
Grouped bar chart
+
+
+ +
Stacked bar graph
+
+
+ +
Stacked area graph
+
+
+ + {% header "h3", "Part-to-a-whole" %} +

Uses size or area to show how some group, entity, or amount breaks down into individual pieces that each represent a proportion of the whole. The data represented in these types of charts aren’t just about how things are divided, it’s about how they’re divided in relation to their whole and to each other. Each part (segment) of the chart represents data points that contribute to the whole and amount to 100% in total. This type makes it easier to identify equal or obviously different values.

+ +
+
+ +
Donut chart
+
+
+ +
Pie chart
+
+
+ +
Stacked area graph (100%)
+
+
+ +
Stacked bar graph (100%)
+
+
+ +
Treemap
+
+
+ + {% header "h3", "Correlations" %} +

Shows relationships and connections between the data or shows correlations between two or more variables. Often used as the first step toward the detection of cause-effect relationships. Use this type of chart to check whether there is any relationship between two variables and also to notice anomalies or clusters in the data.

+ +
+
+ +
Radar
+
+
+ +
Scatterplot
+
+
+ + {% header "h3", "Trend over time" %} +

Analyze data over a time period as a way to identify trends or changes in values. Viewing data over time helps to understand performance, particularly when paired with an established target or goal. Use this type of chart to better understand how something is currently performing and to track any changes over time.

+ +
+
+ +
Area chart
+
+
+ +
Candlestick
+
+
+ +
Histogram
+
+
+ +
Line chart
+
+
+
+ +
+ {% header "h2", "Color palette and usage" %} +

What colors to use and when? Consider the following when choosing the primary color of your data visualization and in what order to add more colors:

+ + {% header "h3", "Blue" %} +

Useful for denoting neutral related metrics.

+ +
+
+ #004487 + blue-900 +
+
+ #0077cc + blue-600 +
+
+ #379fef + blue-400 +
+
+ #0095ff + blue-500 +
+
+ #cfeafe + blue-100 +
+
+ #f2f9ff + blue-050 +
+
+ + {% comment %} + {% icon "Share", "mr2" %} + Open in Google Sheets + {% endcomment %} + + {% header "h3", "Green" %} +

Useful for denoting positive related metrics.

+ +
+
+ #1e472c + color-900 +
+
+ #29603b + color-800 +
+
+ #2f6f44 + color-700 +
+
+ #48a868 + color-500 +
+
+ #a6d9b7 + color-200 +
+
+ #eef8f1 + color-025 +
+
+ + {% header "h3", "Red" %} +

Using for denoting negative metrics.

+ +
+
+ #7a1819 + red-900 +
+
+ #ac2726 + red-700 +
+
+ #d1383d + red-500 +
+
+ #de535e + red-400 +
+
+ #f4b4bb + red-200 +
+
+ #fdf3f4 + red-050 +
+
+ + {% header "h3", "Multi-colored" %} +

Useful for denoting unrelated metrics.

+ +
+
+ #27348b +
+
+ #f2720c + orange-500 +
+
+ #48a868 + green-500 +
+
+ #379fef + blue-400 +
+
+ #f7cc46 +
+
+ #fee3cf + orange-100 +
+
+
+ +
+ {% header "h2", "Accessibility" %} +

It’s important to remember that you know more about the data than the target audience and that others may have a different set of constraints than you do. Make sure your data visualization is making the data clear and accessible to all by:

+
    +
  • Having sufficient contrast with the background for any objects using colour (ex: dots, bars, lines, etc.).
  • +
  • Color must not be the only means of conveying information (consider adding labels).
  • +
  • Avoid overwhelming the user with too much information
  • +
+
+ +
+ {% header "h2", "Sources, resources & inspiration" %} +

Here are some links to help you learn more about data visualization.

+ + +
diff --git a/docs/brand/logo.html b/docs/brand/logo.html index 0015726502..02cf1abfae 100644 --- a/docs/brand/logo.html +++ b/docs/brand/logo.html @@ -6,10 +6,10 @@
{% header "h2", "Stack Overflow" %} -
-
Download as:
- SVG - PNG +
+
Download as:
+ SVG + PNG
{% header "h3", "Logo breakdown" %} @@ -24,27 +24,27 @@

{% header "h3", "Color alternatives" %} -
-
+
+
{% icon "LogoMd", "native wmx100" %}
-
+
{% icon "LogoMd", "native wmx100" %}
-
-
+
+
{% icon "LogoMd", "wmx100" %}
-
+
{% icon "LogoMd", "wmx100" %}
{% header "h3", "Minimum sizes" %} -
- - +
+ +
@@ -55,61 +55,81 @@

{% header "h3", "Stack Overflow for Teams" %} -
-
+
+
-
-
Download:
- SVG - PNG +
+
Download:
+ SVG + PNG
-
+
-
-
Download:
- SVG - PNG +
+
Download:
+ SVG + PNG +
+
+
+ + {% header "h3", "Collectives on Stack Overflow" %} +
+
+ +
+
Download:
+ SVG + PNG +
+
+
+ +
+
Download:
+ SVG + PNG
{% header "h3", "Stack Overflow Talent" %} -
-
+
+
-
-
Download:
- SVG - PNG +
+
Download:
+ SVG + PNG
-
+
-
-
Download:
- SVG - PNG +
+
Download:
+ SVG + PNG
{% header "h3", "Stack Overflow Advertising" %} -
-
+
+
-
-
Download:
- SVG - PNG +
+
Download:
+ SVG + PNG
-
+
-
-
Download:
- SVG - PNG +
+
Download:
+ SVG + PNG
@@ -118,79 +138,79 @@ {% header "h3", "International" %} -
-
+
+
-
-
Download:
- SVG - PNG - PDF +
+
Download:
+ SVG + PNG + PDF
-
+
-
-
Download:
- SVG - PNG - PDF +
+
Download:
+ SVG + PNG + PDF
-
+
-
-
Download:
- SVG - PNG - PDF +
+
Download:
+ SVG + PNG + PDF
-
+
-
-
Download:
- SVG - PNG - PDF +
+
Download:
+ SVG + PNG + PDF
{% header "h3", "Stack Exchange" %} -
-
+
+
-
-
Download:
- SVG - PNG - EPS +
+
Download:
+ SVG + PNG + EPS
-
+
-
-
Download:
- SVG - PNG +
+
Download:
+ SVG + PNG
-
+
-
-
Download:
- SVG - PNG - EPS +
+
Download:
+ SVG + PNG + EPS
-
+
-
-
Download:
- SVG - PNG +
+
Download:
+ SVG + PNG
@@ -199,27 +219,27 @@
{% header "h2", "Stack Overflow Meta" %} -
-
Download as:
- SVG - PNG +
+
Download as:
+ SVG + PNG
{% header "h2", "Stack Exchange" %} -
-
Download as:
- SVG - PNG - EPS +
+
Download as:
+ SVG + PNG + EPS
-
-
Download as:
- SVG - PNG +
+
Download as:
+ SVG + PNG
diff --git a/docs/brand/typography.html b/docs/brand/typography.html new file mode 100644 index 0000000000..c24778fa0e --- /dev/null +++ b/docs/brand/typography.html @@ -0,0 +1,134 @@ +--- +layout: page +title: Typography +description: In our Marketing material we use two fonts, here is some simple usage guidence. +--- + + +
+ {% header "h2", "Headers" %} +

Roboto Slab is an open-source slab serif with geometric forms and friendly and open curves. We use it for headings and numerical call outs.

+ + + {% icon "Share", "mr2" %} + Download at Google Fonts + +
+ +
+ {% header "h2", "Paragraphs & subheadings" %} +

Source Sans Pro is an open-source sans serif that works well for legibility in UI environments.

+ + + {% icon "Share", "mr2" %} + Download at Google Fonts + +
+ +
+ {% header "h2", "Examples" %} +

Some examples of common patterns. Sizing in these examples is based on the Product standards. In other mediums you can just use the relative sizes.

+ + + + {% header "h3", "Hero headline & paragraph" %} +
+{% highlight html %} +

+ Knowledge sharing and collaboration without distractions +

+

+ Stack Overflow for Teams is a knowledge management & collaboration solution that technologists already trust. +

+{% endhighlight %} +
+

+ Knowledge sharing and collaboration without distractions +

+

+ Stack Overflow for Teams is a knowledge management & collaboration solution that technologists already trust. +

+
+
+ + {% header "h3", "Section headline & preface" %} +
+{% highlight html %} +

+ Improves other tools +

+

+ Streamline workflows across the entire organization +

+{% endhighlight %} +
+

+ Improves other tools +

+

+ Streamline workflows across the entire organization +

+
+
+ + {% header "h3", "Item headline & preface" %} +
+{% highlight html %} +

+ Improves other tools +

+

+ Help engineers be more efficient and streamline knowledge sharing using a tool they already love and trust. +

+{% endhighlight %} +
+

+ Software engineers +

+

+ Help engineers be more efficient and streamline knowledge sharing using a tool they already love and trust. +

+
+
+ + {% header "h3", "Numbers (large)" %} +
+{% highlight html %} +
+ 82% +
+
+ of developers visit us at least once per week +
+{% endhighlight %} +
+
+ 82% +
+
+ of developers visit us at least once per week +
+
+
+ + {% header "h3", "Numbers (small)" %} +
+{% highlight html %} +
+ 5,000+ +
+
+ Stack Overflow for Teams instances active every day +
+{% endhighlight %} +
+
+ 5,000+ +
+
+ Stack Overflow for Teams instances active every day +
+
+
+ +
\ No newline at end of file diff --git a/docs/content/examples/alt-text.html b/docs/content/examples/alt-text.html index 11d3537b64..95db536b6a 100644 --- a/docs/content/examples/alt-text.html +++ b/docs/content/examples/alt-text.html @@ -85,12 +85,12 @@

{% endhighlight %}
-
-
+
+
-

Improve efficiency and ship better code

-

There’s a reason the world’s largest developer teams rely on Stack Overflow Enterprise—it leads to better product and allows distributed teams to securely collaborate and share knowledge.

+

Improve efficiency and ship better code

+

There’s a reason the world’s largest developer teams rely on Stack Overflow Enterprise—it leads to better product and allows distributed teams to securely collaborate and share knowledge.

@@ -110,13 +110,13 @@

{% endhighlight %}
-
-
+
+
-
-

TOP LEADERBOARD: 728X90

-

This ad unit is the most visible on the site.

+
+

TOP LEADERBOARD: 728X90

+

This ad unit is the most visible on the site.

@@ -124,12 +124,9 @@

TOP LEADERBOARD: 7

The nearby text here already explains what the graphic illustrates. If there was alt-text here, screen readers would repeat information to the user.

-
-
{% icon "Alert" %}
-
- Note: In these cases, leaving the alt attribute empty (alt="") will cause a screenreader to skip over the image. Never remove the alt-attribute. When a screenreader comes to an image without an alt attribute, it will dictate the filename (Eg. “SO underscore logo dot png”). -
-
+ {% tip %} + Note: In these cases, leaving the alt attribute empty (alt="") will cause a screenreader to skip over the image. Never remove the alt-attribute. When a screenreader comes to an image without an alt attribute, it will dictate the filename (Eg. “SO underscore logo dot png”). + {% endtip %}
{% header "h2", "How to add alt-text" %} diff --git a/docs/content/examples/error-messages.html b/docs/content/examples/error-messages.html index 9dd757edff..d4054b1597 100644 --- a/docs/content/examples/error-messages.html +++ b/docs/content/examples/error-messages.html @@ -31,12 +31,12 @@ Here’s an example of an inline form error message:

-
-
+
+
This SVG file is invalid.
[The error]
-
+
Check its syntax or pick another file.
[How to fix it]
@@ -45,12 +45,12 @@

If we can’t place the specific error, we’re deliberately vague. The best we can do is tell the user how they might fix it.

-
-
+
+
There was a problem syncing data.
[The error]
-
+
Check your database configuration and try again.
[How to fix it]
@@ -175,17 +175,17 @@

Can’t display metrics

You need to restart your data sync.

-
- - +
+ +

Can’t display metrics

You need to restart your data sync.

-
- - +
+ +
diff --git a/docs/content/examples/preferences-settings.html b/docs/content/examples/preferences-settings.html index 66e0d0cce4..40e18a8685 100644 --- a/docs/content/examples/preferences-settings.html +++ b/docs/content/examples/preferences-settings.html @@ -14,91 +14,91 @@ -
-
+
+
- +
-
-
+
+
- +
-
-
+
+
- +
-
-
+
+
- +
-
-
+
+
- +
-
-
+
+
- +
-
-
+
+
- +
-
-
+
+
- +
-
-
+
+
- +
-
-
+
+
- +
@@ -122,26 +122,26 @@ -
-
+
+
-
+
-
-
+
+
-
+
@@ -149,27 +149,27 @@ -
-
-
- - - diff --git a/docs/product/base/current-color.html b/docs/product/base/current-color.html index 0946d32e2f..12cc0418fe 100644 --- a/docs/product/base/current-color.html +++ b/docs/product/base/current-color.html @@ -35,24 +35,24 @@ {% endhighlight %}
-
-
+
+
-
+
-
+
-
+
diff --git a/docs/product/base/cursors.html b/docs/product/base/cursors.html index 36762d52e3..1288afc14a 100644 --- a/docs/product/base/cursors.html +++ b/docs/product/base/cursors.html @@ -37,29 +37,29 @@
{% endhighlight %}
-
-
+
+
.c-auto
-
+
.c-default
-
+
.c-pointer
-
+
.c-text
-
+
.c-wait
-
+
.c-move
-
+
.c-not-allowed
-
+
.c-help
diff --git a/docs/product/base/flex.html b/docs/product/base/flex.html new file mode 100755 index 0000000000..d44e096e22 --- /dev/null +++ b/docs/product/base/flex.html @@ -0,0 +1,1305 @@ +--- +layout: page +title: Flex +description: Stacks provides extensive utility and helper classes for flex layouts. +--- + +
+ {% header "h2", "Basic flex layout" %} +

A flex layout is initiated with the .d-flex class. By default, display: flex; starts a non-wrapping row. To convert it to a column, apply the .fd-column atomic class.

+
+{% highlight html %} +
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
+
.flex--item
+
.flex--item
+
+
+
+
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+ +
+ {% header "h2", "Fluid" %} +

By default, all flex items will only be as wide as their content. If you would like a flex item or all the flex items to fill the remaining space, apply the .fl-grow1 to the individual item, or .flex__fl-equal to the parent to apply to all children.

+ + {% header "h3", "Fluid examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
+
.flex--item.fl-grow1
+
.flex--item
+
+
+
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+
+ {% header "h2", "Fixed cells" %} +

You can either fix the width of an individual element or fix the width of all child elements within a parent container by setting the width on the parent. The cell widths are based on a 12-column flex layout system.

+ + {% header "h3", "Fixed classes" %} +
+ + + + + + + + + + {% for item in flex.flex-item %} + + + + + + {% endfor %} + +
Individual WidthUniform WidthOutput
{{ item.class }}{{ item.all }}{{ item.output }}
+
+ + {% header "h3", "Fixed examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
.flex--item[x]
+
+
+
.flex--item2
+
.flex--item10
+
+
+
+
+
.flex--item[x] and standard .flex--item
+
+
+
.flex--item3
+
.flex--item6
+
.flex--item
+
+
+
+
+
.d-flex.flex__allitems4
+
+
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+
+ +
+ {% header "h2", "Helpers" %} +

We have a few helper classes you can add to a .d-flex container that affect the child .flex--items.

+ + {% header "h3", "Helper classes" %} +
+ + + + + + + + + + {% for item in flex.helpers %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Helpers examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
.flex__center
+
+
.flex--item
+
+
+
+
.flex__fl-shrink0
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.flex__fl-equal
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+ +
+ {% header "h2", "Nested flex layouts" %} +

Flex layouts can be nested within each other. This allows you to create unique, custom layouts without needing to create new, custom code or override existing styles.

+ + {% header "h3", "Nested examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
+
.flex--item
+
.flex--item
+
+
+
.flex--item2
+
.flex--item2
+
+
+
+
+ +
+ {% header "h2", "Gutters" %} +

Sometimes gutters are desired between cells. To do so apply the appropriate class to the parent wrapper. The gutter applies a margin to all sides. The sizes available are the same as the spacing units.

+ + {% header "h3", "Gutter classes" %} +
+ + + + + + + + + {% for item in flex.gutter %} + + + + + {% endfor %} + +
ClassOutput
{{ item.class }}{{ item.output }}
+
+ + {% header "h3", "Gutter examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
+
.gs16
+
.gs16
+
.gs16
+
.gs16
+
+
+
+
+
.gs16.gsx -- Row gutters only
+
.gs16.gsx -- Row gutters only
+
.gs16.gsx -- Row gutters only
+
.gs16.gsx -- Row gutters only
+
+
+
+
+
.gs16.gsy -- Column gutters only
+
.gs16.gsy -- Column gutters only
+
.gs16.gsy -- Column gutters only
+
.gs16.gsy -- Column gutters only
+
+
+
+
+
+ + {% header "h3", "Nested gutters" %} + {% tip, "warning" %} + Note: Nested flex layouts with gutter spacing will conflict with each other in unpredictable ways. TL;DR? Don’t stick a .d-flex directly into a .d-flex, instead stick a .d-flex into a .flex--item like so: + {% endtip %} +

If you are nesting a flex layout with gutter spacing into another flex layout that also has gutter spacing, the child’s parent wrapper margins will be overwritten by the parent. To have the child flex layout’s gutter spacing honored, you have to put the child flex layout within a .flex--item wrapper first. This allows the parent and child flex layout gutter spacing to act correctly without interfering with each other.

+ +
{% icon "Checkmark", "mtn1 mbn1" %} Do
+
+{% highlight html %} +
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
.flex--item
+
+
+
.flex--item
+
.flex--item
+
+
+
+
+
+ +
{% icon "Clear", "mtn1 mbn1" %} Don’t
+
+{% highlight html %} +
+
+
+
+
+
+
+{% endhighlight %} +
+
+
.flex--item
+
+
.flex--item
+
.flex--item
+
+
+
+
+
+ +
+ {% header "h2", "Flex direction" %} +

On a flex container, you can set the direction of the child items.

+ + {% header "h3", "Flex direction classes" %} +
+ + + + + + + + + + {% for item in flex.flex-direction %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Flex direction examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
+
.fd-row
+
Default
+
+
+
.flex--item 1
+
.flex--item 2
+
.flex--item 3
+
+
+
+
.fd-row-reverse
+
+
.flex--item 1
+
.flex--item 2
+
.flex--item 3
+
+
+
+
.fd-column
+
+
.flex--item 1
+
.flex--item 2
+
.flex--item 3
+
+
+
+
.fd-column-reverse
+
+
.flex--item 1
+
.flex--item 2
+
.flex--item 3
+
+
+
+
+
+
+ +
+ {% header "h2", "Flex wrap" %} +

On a flex container, you can control if the children wrap

+ + {% header "h3", "Flex wrap classes" %} +
+ + + + + + + + + + {% for item in flex.flex-wrap %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Flex wrap examples" %} +
+{% highlight html %} +
+
+ … +
+
+
+ … +
+
+
+ … +
+{% endhighlight %} +
+
+
+
.fw-wrap
+
+
.flex--item 1
+
.flex--item 2
+
.flex--item 3
+
.flex--item 4
+
.flex--item 5
+
.flex--item 6
+
.flex--item 7
+
.flex--item 8
+
+
+
+
.fw-reverse
+
+
.flex--item 1
+
.flex--item 2
+
.flex--item 3
+
.flex--item 4
+
.flex--item 5
+
.flex--item 6
+
.flex--item 7
+
.flex--item 8
+
+
+
+
+
.fw-nowrap
+
Default
+
+
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+ +
+ {% header "h2", "Justify content" %} +

Flex items can be controlled with atomic classes on the container’s main axis. This means controlling how a .flex--item is aligned left to right when in an .fd-row, and top and bottom in an .fd-column.

+ + {% header "h3", "Justify content classes" %} +
+ + + + + + + + + + {% for item in flex.justification %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Justify content examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
.jc-center
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.jc-end
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.jc-space-around
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.jc-space-between
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.jc-space-evenly
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
.jc-start
+
Default
+
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+ +
+ {% header "h2", "Align items" %} +

Flex items can be controlled with atomic classes on the container’s cross axis. This means controlling how a .flex--item is aligned top to bottom when in an .fd-row, and left to right in an .fd-column.

+ + {% header "h3", "Align items classes" %} +
+ + + + + + + + + + {% for item in flex.align-items %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Align items examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
.ai-baseline
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.ai-center
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.ai-end
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.ai-start
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
.ai-stretch
+
Default
+
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+ +
+ {% header "h2", "Align content" %} +

Flex items can be controlled with atomic classes on the container’s cross axis.

+ + {% header "h3", "Align content classes" %} +
+ + + + + + + + + + {% for item in flex.align-content %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Align content examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
.ac-center
+
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.ac-end
+
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.ac-space-around
+
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.ac-space-between
+
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
.ac-start
+
Default
+
+
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+ +
+ {% header "h2", "Align self" %} +

A flex container’s align-items can be overridden on individual items within a flex layout.

+ + {% header "h3", "Align self classes" %} +
+ + + + + + + + + + {% for item in flex.align-self %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Align self examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
+
.as-auto
+
Default
+
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.as-baseline
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.as-center
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.as-end
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.as-start
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.as-stretch
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
+ +
+ {% header "h2", "Order" %} +

Within a flex layout, you can force the position of individual elements.

+ + {% header "h3", "Order classes" %} +
+ + + + + + + + + + {% for item in flex.order %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Order examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
.order-first
+
+
.flex--item 1
+
.flex--item 2
+
.flex--item 3
+
+
+
+
.order-last
+
+
.flex--item 1
+
.flex--item 2
+
.flex--item 3
+
+
+
+
+
+
+ +
+ {% header "h2", "Flex shrink and grow" %} +

You can control the growing and shrinking behavior of individual elements within a flex layout

+ + {% header "h3", "Flex classes" %} +
+ + + + + + + + + + {% for item in flex.flex %} + + + + + + {% endfor %} + +
ClassDefinitionResponsive?
{{ item.class }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Flex examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
.fl-grow1
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.fl-grow0
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.fl-shrink1
+
+
.flex--item
+
.flex--
item
+
.flex--item
+
+
+
+
.fl-shrink0
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
.fl-none
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+ +
+
.fl-initial
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+ +
+
.fl-auto
+
+
.flex--item
+
.flex--item.ws2
+
.flex--item
+
+
+ +
+
.fl-equal
+
+
.flex--item
+
.flex--item
+
.flex--item
+
+
+
+
+
+
diff --git a/docs/product/base/grid.html b/docs/product/base/grid.html old mode 100755 new mode 100644 index 7de6309877..fdcee3357c --- a/docs/product/base/grid.html +++ b/docs/product/base/grid.html @@ -1,277 +1,800 @@ --- layout: page title: Grid -description: The Stacks grid system is a flexible, scaffolding system for product layouts. It’s an extensive system that provides fixed cell widths, gutter spacing, and flex atomic classes. +description: Atomic CSS grid classes allow you to quickly add native css grids to your container. --- -
- {% header "h2", "Basic grid" %} -

A grid is initiated with the .grid class. By default, display: flex; starts a non-wrapping row. To convert it to a column, apply the .fd-column helper class.

+ {% header "h2", "Overview" %} + {% tip, "warning", "mb24" %} +

Looking for our old flex grid? Flex layouts have been moved and renamed now that CSS grid is here. Our .grid, and .grid--cell classes have been removed in favor of .d-flex and .flex--item.

+

If you need to continue using the old .grid, and .grid--cell classes, Stacks provides a shim for backwards compatability.

+ {% endtip %} + +

CSS Grids are the most powerful layout system available in CSS. It has two dimensions, meaning it can handle both columns and rows simultaneously, unlike flex layouts which can only do one at a time. Applying .d-grid to a container will lay out its children according to the CSS Grid layout spec. Adding atomic modifying classes will change the layout’s behavior. Applying classes to an individual .grid--item will change that cell’s behavior.

+ + {% header "h3", "Examples" %}
{% highlight html %} -
-
-
-
-
-
-
+
+
{% endhighlight %} -
-
-
-
-
.grid--cell
-
.grid--cell
-
+
+
+ .d-grid .grid__4 .g16 +
.sm:g-af-row
+
+
+
+
.grid--item
+
.grid--col-all
-
-
-
.grid--cell
-
.grid--cell
+
+
.grid--item
+
.grid--col1
+
.md:grid--col-all
+
.grid--row2
+
+
+
.grid--item
+
.grid--col3
+
.md:grid--col-all
+
.grid__2
+ +
.d-grid
+
.g16
+
.grid__2
+
.sm:g-af-row
+
+
+
.grid--item
+
.sm:grid--col-all
+
+
+
.grid--item
+
.sm:grid--col-all
+
+
+
.grid--item
+
.sm:grid--col-all
+
+
+
.grid--item
+
.sm:grid--col-all
+
+
+
.grid--item
+
.grid--col2
+
+
+
.grid--item
+
.grid--col1
+
.md:grid--col2
+
+
+
.grid--item
+
.grid--col-all
+
+
+
.grid--item
+
.md:grid--col2
+
.md:has-row-2
+
+
+
.grid--item
+
.md:grid--col2
+
+
+
.grid--item
+
.md:grid--col2
+
+
+
.grid--item
+
.md:grid--col-all
+
- {% header "h2", "Fluid cells" %} -

By default all child elements of a grid have a default value of flex: 1 0 auto;. This means that by default all cells will only be as wide as their content. If you would like a cell or all the cells to fill the remaining space, apply the .fl1 to the cell, or .grid__fl1 to the parent to apply to all children.

+ {% header "h2", "Spacing" %} +

The most powerful aspect of CSS grids are its native gutters. To add space between columns and rows add one of the following classes to your grid container.

+ {% header "h3", "Spacing classes" %} +
+ + + + + + + + + + + {% for item in grid.spacing %} + + + + + + + {% endfor %} + +
ClassOutputDefinitionResponsive?
.{{ item.class }}{{ item.output }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
- {% header "h3", "Fluid examples" %} + {% header "h3", "Spacing examples" %}
{% highlight html %} -
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
{% endhighlight %} -
-
-
-
-
.grid--cell.fl1
-
.grid--cell
-
+
+
+
+ .g0
-
-
-
.grid--cell
-
.grid--cell
-
.grid--cell
-
+
+
+
+
+
+
+ +
+
+ .g1 +
+
+
+
+
+
+
+ +
+
+ .g2 +
+
+
+
+
+
+
+ +
+
+ .g4 +
+
+
+
+
+
+
+ +
+
+ .g8 +
+
+
+
+
+
+
+ +
+
+ .g12
+
+
+
+
+
+
+ +
+
+ .g16 +
+
+
+
+
+
+
+ +
+
+ .g24 +
+
+
+
+
+
+
+ +
+
+ .g32 +
+
+
+
+
+
+
+ +
+
+ .g48 +
+
+
+
+
+
+
+ +
+
+ .g64 +
+
+
+
+
+
+
- {% header "h2", "Fixed cells" %} -

You can either fix the width of an individual element or fix the width of all child elements within a parent container by setting the width on the parent. The cell widths are based on a 12-column grid system.

+ {% header "h2", "Columns" %} +

To define a discrete number of columns in your grid layout, you can add a grid__[x] modifying class.

- {% header "h3", "Fixed classes" %} + {% header "h3", "Column classes" %}
- +
- - - + + + + - {% for item in grids.grid-cell %} - - - - - + {% for item in grid.column-templates %} + + + + + + {% endfor %}
Individual WidthUniform WidthOutputClassOutputDefinitionResponsive?
{{ item.class }}{{ item.all }}{{ item.output }}
.{{ item.class }}{{ item.output }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
- {% header "h3", "Fixed examples" %} + {% header "h3", "Columns examples" %}
{% highlight html %} -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
{% endhighlight %} -
-
-
-
-
.grid--cell2
-
.grid--cell10
-
-
-
-
-
.grid--cell3
-
.grid--cell6
-
.grid--cell
-
-
-
-
-
.grid--cell
-
.grid--cell
-
.grid--cell
-
.grid--cell
-
-
+
+
+
1
+
+ +
+
1
+
2
+
+ +
+
1
+
2
+
3
+
+ +
+
1
+
2
+
3
+
4
+
+ +
+
1
+
2
+
3
+
4
+
5
+
+ +
+
1
+
2
+
3
+
4
+
5
+
6
+
+ +
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
+ +
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
+ +
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
+ +
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
+ +
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
+ +
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
- {% header "h2", "Nested grids" %} -

Grids can be nested within each other. This allows you to create unique, custom layouts without needing to create new, custom code or override existing styles.

+ {% header "h2", "Column and row spans" %} +

You can apply grid--col[x] to your columns, and grid--row[x] to your rows to span a specific number of columns or rows.

+ {% header "h3", "Column classes" %} +
+ + + + + + + + + + + {% for item in grid.columns %} + + + + + + + {% endfor %} + +
ClassOutputDefinitionResponsive?
.{{ item.class }}{{ item.output }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
-
-
{% icon "Alert" %}
-
- Note: Nested grids with gutter spacing will conflict with each other. If you are nesting a grid with gutter spacing into a grid that also has gutter spacing, the child's parent wrapper margins will be overwritten by the parent. To have the child grid gutter spacing honored, you must place the child grid within a .grid--cell wrapper first. This allows the parent and child grid gutter spacing to act correctly without interfering with each other. + {% header "h3", "Column examples" %} +
+{% highlight html %} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
.grid--col-all
+
+
+
.grid--col1
+
+
+
.grid--col2
+
+
+
.grid--col3
+
+
+
.grid--col4
+
+
+
.grid--col5
+
+
+
.grid--col6
+
+
+
.grid--col7
+
+
+
.grid--col8
+
+
+
.grid--col9
+
+
+
.grid--col10
+
+
+
.grid--col11
+
+
+
.grid--col12
+
- {% header "h3", "Nested examples" %} + {% header "h3", "Row classes" %} +
+ + + + + + + + + + + {% for item in grid.rows %} + + + + + + + {% endfor %} + +
ClassOutputDefinitionResponsive?
.{{ item.class }}{{ item.output }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Row example" %}
{% highlight html %} -
-
-
-
-
-
-
+
+
+
+
+
+
{% endhighlight %} -
-
-
-
-
.grid--cell
-
.grid--cell
-
+
+
+
+
.grid--col2
+
.grid--row4
-
.grid--cell2
-
.grid--cell2
+
.grid--col2
+
.grid--col2
+
.grid--col2
+
.grid--col2
- {% header "h2", "Gutters" %} -

Sometimes gutters are desired between cells. To do so apply the appropriate class to the parent wrapper. The gutter applies a margin to all sides. The sizes available are the same as the spacing units.

+ {% header "h2", "Autoflow" %} +

If you have grid items that you don’t explicitly place on the grid, the auto-placement algorithm kicks in to automatically place the items.

- {% header "h3", "Gutter classes" %} + {% header "h3", "Autoflow classes" %}
- +
- - + + + + - {% for item in grids.gutter %} - - - - + {% for item in grid.autoflow %} + + + + + + {% endfor %}
ClassOutputClassOutputDefinitionResponsive?
{{ item.class }}{{ item.output }}
.{{ item.class }}{{ item.output }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
- {% header "h3", "Gutter examples" %} + {% header "h3", "Autoflow examples" %}
{% highlight html %} -
-
-
-
-
-
-
+
+
+
+{% endhighlight %} +
+
.g-af-row
+
+
1
+
2
+
3
+
+ +
.g-af-column
+
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
+ +
.g-af-dense
+
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
+
+
+
+ +
+ {% header "h2", "Start and end" %} +

If you’d like to offset a column or row and specify its start and end positioning classes, you can apply these atomic classes.

+ + {% header "h3", "Column start and end classes" %} +
+ + + + + + + + + + + {% for item in grid.column-start-end %} + + + + + + + {% endfor %} + +
ClassOutputDefinitionResponsive?
.{{ item.class }}{{ item.output }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Column start and end examples" %} +
+{% highlight html %} +
+
+
+
-
-
-
+{% endhighlight %} +
+
+
.grid--col-start1 .grid--col-end4
+
+
+
.grid--col-start2 .grid--col-end4
+
+
+
.grid--col2 .grid--col-end5
+
+
+
+ + {% header "h3", "Row start and end classes" %} +
+ + + + + + + + + + + {% for item in grid.row-start-end %} + + + + + + + {% endfor %} + +
ClassOutputDefinitionResponsive?
.{{ item.class }}{{ item.output }}{{ item.define }} + {% if item.responsive %} + {% icon "Checkmark", "fc-green-500" %} + {% endif %} +
+
+ + {% header "h3", "Row start and end examples" %} +
+{% highlight html %} +
+
+
+
+
+
{% endhighlight %} -
-
-
-
-
.gs16
-
.gs16
-
.gs16
-
.gs16
-
-
-
-
-
.gs16.gsx -- Row gutters only
-
.gs16.gsx -- Row gutters only
-
.gs16.gsx -- Row gutters only
-
.gs16.gsx -- Row gutters only
-
-
-
-
-
.gs16.gsy -- Column gutters only
-
.gs16.gsy -- Column gutters only
-
.gs16.gsy -- Column gutters only
-
.gs16.gsy -- Column gutters only
-
+
+
+
+
.grid--col2
+
.grid--row-start2
+
.grid--row-end4
+
.grid--col2
+
.grid--col2
+
.grid--col2
+
.grid--col2
- {% header "h2", "Flex classes" %} -

To change a flex property, use one of the following atomic classes.

+ {% header "h2", "Alignment" %} +

On the grid container, you can apply align-items to the y axis and justify-items to the x axis. On individual items, you can apply align-self on the y axis, and justify-self on the x axis.

-
- + {% header "h3", "Alignment classes" %} +
+
- - - + + + + - {% for item in grids.atomic %} - - - + {% for item in grid.alignment %} + + + +
ClassDefinitionResponsive?ClassOutputDefinitionResponsive?
{{ item.class }}

{{ item.define }}

.{{ item.class }}{{ item.output }}{{ item.define }} {% if item.responsive %} {% icon "Checkmark", "fc-green-500" %} @@ -281,4 +804,38 @@ {% endfor %}
+
+ + {% header "h3", "Alignment examples" %} +
+{% highlight html %} +
+
+
+
+ … +
+{% endhighlight %} +
+
Default
+
+
1
+
2
+
3
+
4
+
5
+
6
+
+ +
.ji-center .ai-center
+
+
1 .as-start
+
2
+
3 .as-stretch
+
4 .js-end
+
5
+
6
+
+
+
diff --git a/docs/product/base/interactivity.html b/docs/product/base/interactivity.html index 74530d3949..fa02a36381 100644 --- a/docs/product/base/interactivity.html +++ b/docs/product/base/interactivity.html @@ -35,9 +35,9 @@
{% endhighlight %}
-
- - +
+ +
@@ -74,9 +74,9 @@
{% endhighlight %}
-
-
.us-auto
-
.us-none
+
+
.us-auto
+
.us-none
@@ -85,12 +85,9 @@
{% header "h2", "User drag" %}

The user-drag CSS property controls whether the user can drag an image.

-
-
{% icon "Alert" %}
-
- Note: These classes only work in Safari and Chrome. -
-
+ {% tip %} + Note: These classes only work in Safari and Chrome. + {% endtip %} {% header "h3", "User drag classes" %}
@@ -120,12 +117,12 @@ {% endhighlight %}
-
-
+
+

.ud-auto
-
+

.ud-none
diff --git a/docs/product/base/object-fit.html b/docs/product/base/object-fit.html new file mode 100644 index 0000000000..104c22fee6 --- /dev/null +++ b/docs/product/base/object-fit.html @@ -0,0 +1,122 @@ +--- +layout: page +title: Object fit +description: Atomic classes that control the sizing of an img or video relative to its container. +--- +
+ {% header "h2", "Classes" %} +
+
+ + + + + + + + + {% for atomic in atomics.object-fit %} + + + + + + {% endfor %} + +
ClassOutputDefinition
{{ atomic.class }}{{ atomic.output }}{{ atomic.define }}
+
+ + {% header "h2", "Examples" %} +
+{% highlight html %} + + + + + + +{% endhighlight %} +
+
+
+
.of-contain
+ placeholder for .of-contain + placeholder for .of-contain +
+
+
.of-cover
+ placeholder for .of-cover + placeholder for .of-cover +
+
+
.of-fill
+ placeholder for .of-fill + placeholder for .of-fill +
+
+
.of-none
+ placeholder for .of-none + placeholder for .of-none +
+
+
.of-scale-down
+ placeholder for .of-scale-down + placeholder for .of-scale-down +
+
+
.op-center.of-none
+ placeholder for .op-center.of-none + placeholder for .op-center.of-none +
+
+
+
+
diff --git a/docs/product/base/overflow.html b/docs/product/base/overflow.html index 73c120e463..f3387e0efd 100644 --- a/docs/product/base/overflow.html +++ b/docs/product/base/overflow.html @@ -41,44 +41,44 @@
{% endhighlight %}
-
-
+
+
.overflow-auto
-
+
.overflow-x-auto
-
+
.overflow-y-auto
-
+
.overflow-hidden
-
+
.overflow-x-hidden
-
+
.overflow-y-hidden
-
+
.overflow-scroll
-
+
.overflow-x-scroll
-
+
.overflow-y-scroll
-
+
.overflow-visible
diff --git a/docs/product/base/position.html b/docs/product/base/position.html index cfbdb78f55..4b9df691a3 100644 --- a/docs/product/base/position.html +++ b/docs/product/base/position.html @@ -43,7 +43,7 @@
{% endhighlight %}
-
+
.ps-static
.ps-relative

.t32
r24
.ps-absolute

.t48
.r32
diff --git a/docs/product/base/spacing.html b/docs/product/base/spacing.html index 4cd3e4ac39..b17f01e5e7 100644 --- a/docs/product/base/spacing.html +++ b/docs/product/base/spacing.html @@ -52,7 +52,8 @@ - 0px + 0 + 1px 2px 4px 6px @@ -123,7 +124,7 @@
{% header "h3", "Auto margin classes" %} -

Stacks provides additional automatic margin classes. These come in handy when positioning individual grid cells within flex layouts, or horizontally centering a block-level element.

+

Stacks provides additional automatic margin classes. These come in handy when positioning individual flex items within flex layouts, or horizontally centering a block-level element.

@@ -225,18 +226,19 @@ - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/docs/product/base/transitions.html b/docs/product/base/transitions.html index dcc62845f1..d82e0ed286 100644 --- a/docs/product/base/transitions.html +++ b/docs/product/base/transitions.html @@ -37,8 +37,8 @@
{% endhighlight %}
-
-
+
+
.t
@@ -53,11 +53,11 @@
{% endhighlight %}
-
-
+
+
.t-slow
-
+
.t-fast
@@ -75,17 +75,17 @@
{% endhighlight %}
-
-
+
+
.t-unset
-
+
.t-bg
-
+
.t-opacity
-
+
.t-shadow
@@ -100,11 +100,11 @@
{% endhighlight %}
-
-
+
+
.t-delay
-
+
.t-delay-unset
diff --git a/docs/product/base/truncation.html b/docs/product/base/truncation.html index e8914b80e5..f1dbca4355 100644 --- a/docs/product/base/truncation.html +++ b/docs/product/base/truncation.html @@ -48,7 +48,7 @@
{% header "h2", "Examples" %} {% header "h3", "Ellipses" %} -

CSS offers truncation on arbitrarily-long strings. This can help sanitize user-inputted things like bios, locations, or display names. In order for text truncation to work, it should be applied to a block-level element.

+

CSS offers truncation on arbitrarily-long strings. This can help sanitize user-inputted things like bios, locations, or display names. In order for text truncation to work, it should be applied to a block-level element. Truncation can only apply to text/strings, not arbitrary block-level elements.

{% highlight html %}

diff --git a/docs/product/base/typography.html b/docs/product/base/typography.html index a1e7ad3f7b..9c2c5949b3 100644 --- a/docs/product/base/typography.html +++ b/docs/product/base/typography.html @@ -49,19 +49,19 @@ {% endhighlight %}
-
-
Font Weight: Normal
-
Font Weight: Bold
-
Font Style: Normal
-
Font Style: Italic
-
Font Style: Unset
-
Text Transform: Capitalize
-
Text Transform: Lowercase
-
Text Transform: Uppercase
-
Text Transform: None
-
Text Transform: Unset
-
Text Decoration: Underline
-
Text Decoration: None
+
+
Font Weight: Normal
+
Font Weight: Bold
+
Font Style: Normal
+
Font Style: Italic
+
Font Style: Unset
+
Text Transform: Capitalize
+
Text Transform: Lowercase
+
Text Transform: Uppercase
+
Text Transform: None
+
Text Transform: Unset
+
Text Decoration: Underline
+
Text Decoration: None
@@ -113,23 +113,23 @@

White-space: Pre-line

White-space: Unset

-

Break word

+

Break word

Truncate: …

{% endhighlight %} -
-

Text Align: Left

-

Text Align: Center

-

Text Align: Right

-

Text Align: Justify — Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

-

Text Align: Unset

-

White-space: Normal

-

White-space: Nowrap

-

White-space: Pre

-

White-space: Pre-wrap

-

White-space: Pre-line

-

White-space: Unset

-

Word Wrap: Break word

+
+

Text Align: Left

+

Text Align: Center

+

Text Align: Right

+

Text Align: Justify — Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+

Text Align: Unset

+

White-space: Normal

+

White-space: Nowrap

+

White-space: Pre

+

White-space: Pre-wrap

+

White-space: Pre-line

+

White-space: Unset

+

Break word: MethionylglutaminylarginylhionylglutaminylargintyrosylglutamylmethionylglutaminylarginyltyrlarginyltyrosylglutamylMethionylglutaminylarginyltyrosylglutamylnyltyrosylserinemethionylglutaminylargiglutamylmethionyosylglutamylmethionylglutaminylglutaminylarginyltyrosylglutamylmethionylglutaminylarginyltyrosylglutamylmetyltyrosylglutamylserine

@@ -143,18 +143,18 @@

{% endhighlight %} -
-
+
+

Sans Serif

-

Arial, "Helvetica Neue", Helvetica, sans-serif

+

-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"

-
+

Serif

-

Georgia, Times New Roman, Times, serif

+

Georgia, Cambria, "Times New Roman", Times, serif

-
+

Monospace

-

Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif

+

"SF Mono", SFMono-Regular, ui-monospace, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace

@@ -204,11 +204,11 @@

{% endhighlight %} -
+
{% for term in typography.fontsize %} -
-
{{ term.label }}
-
+
+
{{ term.label }}
+
{{ term.define }} {{ term.responsive }}
@@ -224,14 +224,14 @@

{% endhighlight %} -
-
-
Category
-
Category Title (12px)
+
+
+
Category
+
Category Title (12px)
-
-
Category (Has Border)
-
Category Title (12px)
+
+
Category (Has Border)
+
Category Title (12px)
@@ -249,14 +249,14 @@

{% endhighlight %} -
-

Line Height XS: This sets the line-height value to 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

-

Line Height SM: This sets the line-height value to 1.13. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

-

Line Height MD: This sets the line-height value to 1.26. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

-

Line Height LG: This sets the line-height value to 1.4. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

-

Line Height XL: This sets the line-height value to 1.53. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

-

Line Height XXL: This sets the line-height value to 1.67. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

-

Line Height Unset: This sets the line-height value to initial. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

+
+

Line Height XS: This sets the line-height value to 1. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

+

Line Height SM: This sets the line-height value to 1.15. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

+

Line Height MD: This sets the line-height value to 1.3. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

+

Line Height LG: This sets the line-height value to 1.6. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

+

Line Height XL: This sets the line-height value to 1.92. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

+

Line Height XXL: This sets the line-height value to 2. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

+

Line Height Unset: This sets the line-height value to initial. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

@@ -269,11 +269,11 @@

{% endhighlight %} -
-
+
+
This text will not be hyphenated when large words break—longer words are broken by .ow-break-word.
-
+
This text will be hyphenated when large words break. .ow-break-word shouldn’t be necessary since breaks are implied by hyphenation rules.
diff --git a/docs/product/base/visibility.html b/docs/product/base/visibility.html index 2dea2294ba..8d200dcf11 100644 --- a/docs/product/base/visibility.html +++ b/docs/product/base/visibility.html @@ -32,14 +32,14 @@
{% endhighlight %}
-
-
+
+
.v-visible
-
+
.v-visible-sr
-
+
.v-hidden
diff --git a/docs/product/base/width-height.html b/docs/product/base/width-height.html index a780ae6d62..68d37fcbaf 100644 --- a/docs/product/base/width-height.html +++ b/docs/product/base/width-height.html @@ -6,7 +6,7 @@
{% header "h2", "Widths" %} {% header "h3", "Width classes" %} -

Width classes are provided at each fixed stop of our sizing scale.

+

Width classes are provided at each fixed stop of our pixel-based sizing scale.

Prefix 02468121624324864961281px2px4px6px8px12px16px24px32px48px64px96px128px Responsive?
@@ -49,54 +49,54 @@
{% endhighlight %}
-
-
-
-
.w2
+
+
+
+
.w2
-
-
-
.w4
+
+
+
.w4
-
-
-
.w6
+
+
+
.w6
-
-
-
.w8
+
+
+
.w8
-
-
-
.w12
+
+
+
.w12
-
-
-
.w16
+
+
+
.w16
-
-
-
.w24
+
+
+
.w24
-
-
-
.w32
+
+
+
.w32
-
-
-
.w48
+
+
+
.w48
-
-
-
.w64
+
+
+
.w64
-
-
-
.w96
+
+
+
.w96
-
-
-
.w128
+
+
+
.w128
@@ -149,35 +149,35 @@
{% endhighlight %}
-
-
+
+
.w100
-
+
.w10
.w90
-
+
.w20
.w80
-
+
.w25
.w75
-
+
.w30
.w70
-
+
.w33
.w66
-
+
.w40
.w60
-
+
.w50
.w50
@@ -188,8 +188,10 @@
{% header "h2", "Static widths" %} +

Static widths are based on the full width of our 12-column grid. The grid is defined in rems, which are tied to the base font size. At the default font size, the full width is 1264px. A single column is approximately 105px.

+

At the smallest breakpoint, our font size is reduced, and these static widths are therefore also reduced.

+ {% header "h3", "Static width classes" %} -

Static widths are based on the full site width of 1264px.

@@ -234,19 +236,19 @@
{% endhighlight %}
-
-
.ws1
-
.ws2
-
.ws3
-
.ws4
-
.ws5
-
.ws6
-
.ws7
-
.ws8
-
.ws9
-
.ws10
-
.ws11
-
.ws12
+
+
.ws1
+
.ws2
+
.ws3
+
.ws4
+
.ws5
+
.ws6
+
.ws7
+
.ws8
+
.ws9
+
.ws10
+
.ws11
+
.ws12
@@ -302,22 +304,22 @@
{% endhighlight %}
-
-
.wmx1
-
.wmx2
-
.wmx25
-
.wmx3
-
.wmx4
-
.wmx5
-
.wmx50
-
.wmx6
-
.wmx7
-
.wmx75
-
.wmx8
-
.wmx9
-
.wmx10
-
.wmx11
-
.wmx12
+
+
.wmx1
+
.wmx2
+
.wmx25
+
.wmx3
+
.wmx4
+
.wmx5
+
.wmx50
+
.wmx6
+
.wmx7
+
.wmx75
+
.wmx8
+
.wmx9
+
.wmx10
+
.wmx11
+
.wmx12
@@ -374,23 +376,23 @@
{% endhighlight %}
-
-
.wmn0
-
.wmn1
-
.wmn2
-
.wmn25
-
.wmn3
-
.wmn4
-
.wmn5
-
.wmn50
-
.wmn6
-
.wmn7
-
.wmn75
-
.wmn8
-
.wmn9
-
.wmn10
-
.wmn11
-
.wmn12
+
+
.wmn0
+
.wmn1
+
.wmn2
+
.wmn25
+
.wmn3
+
.wmn4
+
.wmn5
+
.wmn50
+
.wmn6
+
.wmn7
+
.wmn75
+
.wmn8
+
.wmn9
+
.wmn10
+
.wmn11
+
.wmn12
@@ -442,77 +444,77 @@
{% endhighlight %}
-
-
-
-
.h2
-
+
+
+
+
.h2
+
-
-
-
.h4
-
+
+
+
.h4
+
-
-
-
.h6
-
+
+
+
.h6
+
-
-
-
.h8
-
+
+
+
.h8
+
-
-
-
.h12
-
+
+
+
.h12
+
-
-
-
.h16
-
+
+
+
.h16
+
-
-
-
.h24
-
+
+
+
.h24
+
-
-
-
.h32
-
+
+
+
.h32
+
-
-
-
.h48
-
+
+
+
.h48
+
-
-
-
.h64
-
+
+
+
.h64
+
-
-
-
.h96
-
+
+
+
.h96
+
-
-
-
.h128
-
+
+
+
.h128
+
diff --git a/docs/product/components/activity-indicator.html b/docs/product/components/activity-indicator.html new file mode 100644 index 0000000000..99cf41ac50 --- /dev/null +++ b/docs/product/components/activity-indicator.html @@ -0,0 +1,156 @@ +--- +layout: page +title: Activity indicator +description: Stacks provides a small jewel for indicating new activity. +--- +
+ {% header "h2", "Classes" %} +
+
+ + + + + + + + + {% for item in activity-indicator.indicator %} + + + + + + {% endfor %} + +
ClassApplied toDescription
{{ item.class }}{% if item.applies == "N/A" %}{{ item.applies }}{% else %}{{ item.applies }}{% endif %}{{ item.description }}
+
+ +
+ {% header "h2", "Examples" %} + {% header "h3", "Default" %} +

By default, our indicator has no positioning attached to it. Depending on your context, you can modify the activity indicator’s positioning using any combination of atomic classes. Since our activity indicator has no inherent semantic meaning, make sure to include visually-hidden, screenreader-only text.

+
+{% highlight html %} +
+
New activity
+
+ +
+ … +
+
+ +
+ … +
+
+ +
+ … +
+
+ +
+ … +
+ + +
+
+
+
+
+ @Svg.ShieldXSm.With("native s-avatar--badge") +
+ +
+ +
+ @Svg.Bell + +
+
+
+
+{% endhighlight %} +
+
+
+
New activity
+
+ +
+ 3 +
New activity
+
+ +
+ 12 +
New activity
+
+ +
+ 370 +
New activity
+
+ +
+ New +
+ + + +
+
+ {% icon "Bell" %} + +
+
New activity
+
+
+
+
+
+
+ + {% header "h3", "Variations" %} +

Stacks also provides alternative styling for success, warning, and danger states.

+
+{% highlight html %} +
+
+
+
+
+
+
+
+
+{% endhighlight %} +
+
+
+
New activity
+
+
+
New activity
+
+
+
New activity
+
+
+
+
+
diff --git a/docs/product/components/avatars.html b/docs/product/components/avatars.html index 9289dc4fe2..b4c96a6f1d 100644 --- a/docs/product/components/avatars.html +++ b/docs/product/components/avatars.html @@ -207,7 +207,7 @@ -
+
H
{% icon "ShieldXSm", "native s-avatar--badge" %}
@@ -235,7 +235,7 @@
- +
H
{% icon "ShieldXSm", "native s-avatar--badge" %}
@@ -258,7 +258,7 @@ - +
H
{% icon "ShieldXSm", "native s-avatar--badge" %}
@@ -281,7 +281,7 @@ - +
H
{% icon "ShieldXSm", "native s-avatar--badge" %}
@@ -304,7 +304,7 @@ - +
H
{% icon "ShieldXSm", "native s-avatar--badge" %}
@@ -327,7 +327,7 @@ - +
H
{% icon "ShieldXSm", "native s-avatar--badge" %}
@@ -350,7 +350,7 @@ - +
H
{% icon "ShieldXSm", "native s-avatar--badge" %}
diff --git a/docs/product/components/badges.html b/docs/product/components/badges.html index ce7ef0867c..782d0de54b 100644 --- a/docs/product/components/badges.html +++ b/docs/product/components/badges.html @@ -45,12 +45,12 @@ Great Question - + Favorite Question - + @@ -59,21 +59,21 @@ {% endhighlight %}
-
- +
+ Great Question - + - + Favorite Question - + - + Altruist - +
@@ -85,32 +85,32 @@ 635 - + 7624 - + 8234 - + {% endhighlight %}
-
- +
+ 635 - + 7624 - + 8234 @@ -130,48 +130,44 @@ 99+ {% endhighlight %}
-
- +100 - 38 - 154 - +15 - -2 - 99+ +
+ +100 + 38 + 154 + +15 + -2 + 99+
- -{% header "h3", "User badges" %} -
+ {% header "h3", "User badges" %} +
{% highlight html %} Admin -Admin -Admin +Admin +Admin Moderator -Mod -Mod +Mod +Mod Staff -Staff -Staff - +Staff +Staff {% endhighlight %} -
-
- Admin - Admin - Admin - Moderator - Mod - Mod - Staff - Staff - Staff +
+
+ Admin + Admin + Admin + Moderator + Mod + Mod + Staff + Staff + Staff +
-
- - {% header "h3", "Badge sizes" %}
@@ -182,11 +178,11 @@ Extra small {% endhighlight %}
-
- Regular - Small - Small gold - Extra small +
+ Regular + Small + Small gold + Extra small
diff --git a/docs/product/components/banners.html b/docs/product/components/banners.html index 8fb4822ba1..1b71221f37 100644 --- a/docs/product/components/banners.html +++ b/docs/product/components/banners.html @@ -18,17 +18,17 @@ }