├── .editorconfig ├── .gitattributes ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .modernizrrc.js ├── .prettierignore ├── .release-it.js ├── CHANGES.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── Makefile ├── README.md ├── RELEASE.md ├── _sass ├── _fonts.scss ├── _mixins.scss ├── _patterns.scss ├── _settings.scss └── components │ ├── _avatar.scss │ ├── _button-bar.scss │ ├── _button.scss │ ├── _form.scss │ ├── _icon.scss │ ├── _photoswipe.scss │ └── _tiny-content.scss ├── babel.config.js ├── commitlint.config.js ├── docs ├── designer │ ├── markup-styleguide.md │ ├── parameters.md │ ├── tips-and-tricks.md │ └── what-is-patternslib.md ├── developer │ ├── create-a-pattern.md │ ├── module-federation.md │ ├── parser.md │ ├── patterns.rst │ ├── store.md │ ├── styleguide.md │ └── usage-recipies.md └── history │ ├── 1.md │ ├── 2.md │ ├── 3.md │ ├── 4.md │ ├── 5.md │ ├── 6.md │ ├── 7.md │ ├── 8.md │ ├── UPGRADE-2-TO-3.md │ └── index.md ├── eslint.config.js ├── index.html ├── jest.config.js ├── package.json ├── prettier.config.js ├── src ├── core │ ├── base.js │ ├── base.test.js │ ├── basepattern.js │ ├── basepattern.md │ ├── basepattern.test.js │ ├── dom.js │ ├── dom.test.js │ ├── events.js │ ├── events.test.js │ ├── feature-detection.js │ ├── feature-detection.md │ ├── i18n.js │ ├── jquery-ext.js │ ├── jquery-ext.test.js │ ├── logging.js │ ├── mockup-parser.js │ ├── parser.js │ ├── parser.test.js │ ├── polyfills.js │ ├── polyfills.test.js │ ├── push_kit.js │ ├── registry.js │ ├── registry.test.js │ ├── remove.js │ ├── store.js │ ├── store.test.js │ ├── url.js │ ├── url.test.js │ ├── utils.js │ ├── utils.test.js │ ├── uuid.js │ └── uuid.test.js ├── index.js ├── lib │ ├── depends_parse.js │ ├── depends_parse.pegjs │ ├── depends_parse.test.js │ ├── dependshandler.js │ ├── dependshandler.test.js │ └── input-change-events.js ├── pat │ ├── ajax │ │ ├── ajax.js │ │ └── ajax.test.js │ ├── auto-scale │ │ ├── _auto-scale.scss │ │ ├── auto-scale.js │ │ ├── documentation.md │ │ └── index.html │ ├── auto-submit │ │ ├── auto-submit.js │ │ ├── auto-submit.test.js │ │ ├── documentation.md │ │ ├── index.html │ │ ├── pattern-test-response.html │ │ └── placeholder.gif │ ├── auto-suggest │ │ ├── _auto-suggest.scss │ │ ├── auto-suggest.js │ │ ├── auto-suggest.test.js │ │ ├── data.json │ │ ├── datagroup.json │ │ ├── documentation.md │ │ ├── index.html │ │ ├── select2-spinner.gif │ │ ├── select2.png │ │ └── select2x2.png │ ├── autofocus │ │ ├── autofocus.js │ │ ├── autofocus.test.js │ │ ├── documentation.md │ │ ├── index-iframed.html │ │ └── index.html │ ├── breadcrumbs │ │ └── breadcrumbs.js │ ├── bumper │ │ ├── bumper.js │ │ ├── bumper.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── calendar │ │ ├── calendar.js │ │ ├── calendar.test.js │ │ ├── documentation.md │ │ ├── index.html │ │ ├── test_add_event.html │ │ ├── test_event.html │ │ ├── test_event_source.json │ │ └── test_event_source2.json │ ├── carousel │ │ ├── _carousel.scss │ │ ├── ajax-loader.gif │ │ ├── carousel-arrows.png │ │ ├── carousel-arrows.psd │ │ ├── carousel.js │ │ ├── carousel.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── checklist │ │ ├── _checklist.scss │ │ ├── checklist.js │ │ ├── checklist.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── clone-code │ │ ├── clone-code.js │ │ ├── clone-code.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── clone │ │ ├── clone.js │ │ ├── clone.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── close-panel │ │ ├── close-panel.js │ │ ├── close-panel.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── collapsible │ │ ├── _collapsible.scss │ │ ├── collapsible-sources.html │ │ ├── collapsible.js │ │ ├── collapsible.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── colour-picker │ │ ├── _colour-picker.scss │ │ ├── colour-picker.js │ │ ├── documentation.md │ │ └── index.html │ ├── date-picker │ │ ├── _date-picker.scss │ │ ├── date-picker.js │ │ ├── date-picker.test.js │ │ ├── documentation.md │ │ ├── i18n.json │ │ └── index.html │ ├── datetime-picker │ │ ├── _datetime-picker.scss │ │ ├── datetime-picker.js │ │ ├── datetime-picker.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── depends │ │ ├── depends.js │ │ ├── depends.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── display-time │ │ ├── display-time.js │ │ ├── display-time.test.js │ │ ├── documentation.md │ │ └── index.html │ ├── equaliser │ │ ├── _equaliser.scss │ │ ├── documentation.md │ │ ├── equaliser.js │ │ ├── equaliser.test.js │ │ └── index.html │ ├── expandable-tree │ │ ├── _expandable-tree.scss │ │ ├── documentation.md │ │ ├── expandable-tree.js │ │ └── index.html │ ├── focus │ │ ├── _focus.scss │ │ ├── documentation.md │ │ ├── focus.js │ │ ├── focus.test.js │ │ └── index.html │ ├── form-state │ │ └── form-state.js │ ├── forward │ │ ├── documentation.md │ │ ├── forward.js │ │ ├── forward.test.js │ │ └── index.html │ ├── fullscreen │ │ ├── _fullscreen.scss │ │ ├── documentation.md │ │ ├── fullscreen-close.js │ │ ├── fullscreen.js │ │ ├── fullscreen.test.js │ │ └── index.html │ ├── gallery │ │ ├── _gallery.scss │ │ ├── default-skin.png │ │ ├── default-skin.svg │ │ ├── documentation.md │ │ ├── full-1.jpg │ │ ├── full-2.jpg │ │ ├── full-3.jpg │ │ ├── full-4.jpg │ │ ├── gallery.js │ │ ├── gallery.test.js │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── index.html │ │ ├── loader.gif │ │ ├── preloader.gif │ │ ├── template.html │ │ ├── thumb-1.jpg │ │ ├── thumb-2.jpg │ │ └── thumb-3.jpg │ ├── grid │ │ ├── _grid.scss │ │ ├── documentation.md │ │ ├── grid.js │ │ ├── index.html │ │ ├── offsets.png │ │ └── source-ordering.png │ ├── image-crop │ │ ├── Jcrop.gif │ │ ├── _image-crop.scss │ │ ├── documentation.md │ │ ├── image-crop.js │ │ ├── image-crop.test.js │ │ ├── index.html │ │ └── pool.jpg │ ├── inject │ │ ├── _inject.scss │ │ ├── _injection.scss │ │ ├── demo │ │ │ ├── backend-action.html │ │ │ ├── cocteau.jpg │ │ │ ├── history-inject-source.html │ │ │ ├── history-page1.html │ │ │ ├── history-page2.html │ │ │ ├── history-page3.html │ │ │ ├── history.html │ │ │ ├── inject-form.html │ │ │ ├── inject-sources.html │ │ │ ├── inject-text.html │ │ │ ├── pattern-test-response.html │ │ │ ├── rilke.jpg │ │ │ ├── test_404.html │ │ │ └── wilde.jpg │ │ ├── documentation.md │ │ ├── index.html │ │ ├── inject.js │ │ ├── inject.test.js │ │ ├── injection-modal.svg │ │ ├── injection-multiple.svg │ │ └── injection-single.svg │ ├── legend │ │ ├── legend.js │ │ └── legend.test.js │ ├── markdown │ │ ├── content │ │ │ ├── content │ │ │ └── content.md │ │ ├── documentation.md │ │ ├── index.html │ │ ├── markdown.js │ │ └── markdown.test.js │ ├── masonry │ │ ├── README.md │ │ ├── _masonry.scss │ │ ├── documentation.md │ │ ├── images │ │ │ ├── bouquet.jpg │ │ │ ├── flower-of-happiness.jpg │ │ │ ├── lillies.jpg │ │ │ ├── petunia.jpg │ │ │ └── woolflowers.jpg │ │ ├── index.html │ │ ├── masonry.js │ │ └── masonry.test.js │ ├── menu │ │ ├── _menu.scss │ │ ├── documentation.md │ │ ├── index.html │ │ ├── menu.js │ │ └── menu.test.js │ ├── minimalpattern │ │ ├── documentation.md │ │ ├── index.html │ │ ├── minimalpattern.js │ │ └── minimalpattern.test.js │ ├── modal │ │ ├── _modal.scss │ │ ├── buttons-modal.png │ │ ├── documentation.md │ │ ├── index-modal.html │ │ ├── index.html │ │ ├── modal.js │ │ └── modal.test.js │ ├── navigation │ │ ├── documentation.md │ │ ├── index.html │ │ ├── navigation.js │ │ └── navigation.test.js │ ├── notification │ │ ├── _notification.scss │ │ ├── documentation.md │ │ ├── index.html │ │ ├── inject-notification.html │ │ ├── inject-source.html │ │ ├── notification.js │ │ └── notification.test.js │ ├── push │ │ ├── documentation.md │ │ ├── index-push-content.html │ │ ├── index-push-messages.html │ │ ├── index.html │ │ ├── push.js │ │ └── tools │ │ │ ├── .gitignore │ │ │ ├── Makefile │ │ │ ├── README.md │ │ │ ├── rabbitmq_enabled_plugins │ │ │ └── send.py │ ├── scroll-box │ │ ├── documentation.md │ │ ├── index.html │ │ ├── scroll-box.js │ │ └── scroll-box.test.js │ ├── scroll-marker │ │ ├── documentation.md │ │ ├── index.html │ │ ├── scroll-marker.js │ │ └── scroll-marker.test.js │ ├── scroll │ │ ├── documentation.md │ │ ├── index.html │ │ ├── scroll.js │ │ ├── scroll.test.js │ │ ├── scrollcalculation.svg │ │ └── test-scrollbody.html │ ├── selectbox │ │ ├── documentation.md │ │ ├── index.html │ │ ├── selectbox.js │ │ └── selectbox.test.js │ ├── separator │ │ └── _separator.scss │ ├── slides │ │ ├── documentation.md │ │ ├── index.html │ │ ├── media │ │ │ ├── binnenhof.jpg │ │ │ ├── chrome-gradient-fix.png │ │ │ ├── dialogues.jpg │ │ │ ├── joker.png │ │ │ ├── logo-rijksoverheid-dp.svg │ │ │ ├── pearl-bar.jpg │ │ │ ├── pearl-jewel.png │ │ │ ├── pearl-model-fingers.png │ │ │ ├── pearl-model.png │ │ │ ├── pearl-pearl.png │ │ │ └── pearl-slogan.png │ │ ├── notes.md │ │ ├── slides.js │ │ ├── slides.test.js │ │ ├── standalone-test.html │ │ └── style │ │ │ ├── animate.css │ │ │ ├── README.md │ │ │ ├── animate.css │ │ │ └── animate.min.css │ │ │ ├── fontello │ │ │ ├── LICENSE.txt │ │ │ ├── README.txt │ │ │ ├── config.json │ │ │ ├── css │ │ │ │ ├── animation.css │ │ │ │ ├── fontello-codes.css │ │ │ │ ├── fontello-ie7-codes.css │ │ │ │ └── fontello-ie7.css │ │ │ ├── demo.html │ │ │ └── font │ │ │ │ ├── fontello.eot │ │ │ │ ├── fontello.svg │ │ │ │ ├── fontello.ttf │ │ │ │ └── fontello.woff │ │ │ ├── images │ │ │ ├── brandmark.png │ │ │ └── logo.png │ │ │ └── slides.css │ ├── sortable │ │ ├── _sortable.scss │ │ ├── documentation.md │ │ ├── index.html │ │ ├── sortable.js │ │ └── sortable.test.js │ ├── stacks │ │ ├── _stacks.scss │ │ ├── documentation.md │ │ ├── index.html │ │ ├── stacks.js │ │ └── stacks.test.js │ ├── subform │ │ ├── documentation.md │ │ ├── form-response.html │ │ ├── index.html │ │ ├── pattern-test-response.html │ │ ├── subform-other-response.html │ │ ├── subform-response.html │ │ ├── subform.js │ │ └── subform.test.js │ ├── switch │ │ ├── _switch.scss │ │ ├── documentation.md │ │ ├── index.html │ │ ├── switch.js │ │ └── switch.test.js │ ├── syntax-highlight │ │ ├── _syntax-highlight.scss │ │ ├── documentation.md │ │ ├── index.html │ │ ├── syntax-highlight.js │ │ └── syntax-highlight.test.js │ ├── tabs │ │ ├── documentation.md │ │ ├── index.html │ │ ├── tabs.js │ │ ├── tabs.scss │ │ └── tabs.test.js │ ├── toggle │ │ ├── _toggle.scss │ │ ├── documentation.md │ │ ├── index.html │ │ ├── toggle.js │ │ └── toggle.test.js │ ├── tooltip │ │ ├── _tooltip.scss │ │ ├── documentation.md │ │ ├── index.html │ │ ├── pattern-test-response.html │ │ ├── tooltip.js │ │ └── tooltip.test.js │ ├── validation │ │ ├── documentation.md │ │ ├── index.html │ │ ├── validation.js │ │ └── validation.test.js │ └── zoom │ │ ├── documentation.md │ │ ├── images │ │ ├── slide.002.jpg │ │ ├── slide.003.jpg │ │ ├── slide.018.jpg │ │ ├── slide.019.jpg │ │ └── slide.032.jpg │ │ ├── index.html │ │ ├── zoom.js │ │ └── zoom.test.js ├── patterns.js └── setup-tests.js ├── style ├── common.css ├── fontello │ ├── LICENSE.txt │ ├── README.txt │ ├── config.json │ ├── css │ │ ├── animation.css │ │ ├── fontello-codes.css │ │ ├── fontello-embedded.css │ │ ├── fontello-ie7-codes.css │ │ ├── fontello-ie7.css │ │ └── fontello.css │ ├── demo.html │ └── font │ │ ├── fontello.eot │ │ ├── fontello.svg │ │ ├── fontello.ttf │ │ └── fontello.woff ├── fonts │ ├── Source_Sans_Pro_300.eot │ ├── Source_Sans_Pro_300.svg │ ├── Source_Sans_Pro_300.ttf │ ├── Source_Sans_Pro_300.woff │ ├── Source_Sans_Pro_400.eot │ ├── Source_Sans_Pro_400.svg │ ├── Source_Sans_Pro_400.ttf │ ├── Source_Sans_Pro_400.woff │ ├── Source_Sans_Pro_700.eot │ ├── Source_Sans_Pro_700.svg │ ├── Source_Sans_Pro_700.ttf │ ├── Source_Sans_Pro_700.woff │ ├── font.css │ └── patticons │ │ ├── patticons.otf │ │ ├── patticons.svg │ │ ├── patticons.ttf │ │ └── patticons.woff ├── pattern-icons.svg ├── patterns.css └── select2x2.png ├── webpack ├── module_federation--dynamic-federation.js ├── module_federation--getOrLoadRemote.js ├── module_federation.js └── webpack.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset = utf-8 3 | end_of_line = lf 4 | indent_style = space 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | 8 | [*{js,jsx,vue,ts,json}] 9 | indent_size = 4 10 | 11 | [*.{css,scss,xml,html,yml}] 12 | indent_size = 2 13 | 14 | [Makefile] 15 | indent_style = tab 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | CHANGES.md merge=union 2 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: test 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | build: 11 | name: test 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: actions/setup-node@v4 16 | with: 17 | node-version: '22' 18 | cache: 'yarn' 19 | - run: | 20 | make install 21 | make check 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.css.map 2 | *.log 3 | *.swo 4 | *.swp 5 | *~ 6 | .env 7 | .DS_Store 8 | .bundle 9 | .sass-cache 10 | /paternslib.sublime-project 11 | /paternslib.sublime-workspace 12 | /stamp-yarn 13 | Gemfile.lock 14 | Patterns-site/ 15 | cache/ 16 | coverage/ 17 | dist/ 18 | node_modules/ 19 | src/pat/**/*.css 20 | stats.html 21 | stats.json 22 | test-reports 23 | webpack/cache/ 24 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | coverage/ 3 | dist/ 4 | node_modules/ 5 | stats.json 6 | style/ 7 | -------------------------------------------------------------------------------- /.release-it.js: -------------------------------------------------------------------------------- 1 | const config = require("@patternslib/dev/.release-it.js"); 2 | 3 | config.plugins["@release-it/conventional-changelog"].header = 4 | "# Changelog\n\nSee the [history](./docs/history/index.md) for older changelog entries.\n\n"; 5 | 6 | module.exports = config; 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | ## Reporting problems 4 | 5 | If you find a bug in Patterns please report to it us. Doing so is very simple: 6 | 7 | - Make sure you have a [GitHub account](https://github.com/signup/free). 8 | - [Submit a ticket for your 9 | issue](https://github.com/Patternslib/Patterns/issues/new), assuming one does 10 | not already exist. Make sure to clearly describe the issue, including steps 11 | to reproduce when it is a bug. 12 | - If possible include a small test case demonstrating the problem. This can either 13 | be provided in the ticket itself, or through a pointer to a 14 | [JSFiddle](http://jsfiddle.net/). 15 | 16 | ## Contributing code 17 | 18 | All code contributions are extremely welcome. In order to contribute please make 19 | sure you have do the following: 20 | 21 | - Read our [code style guide](docs/developer/styleguide.md). 22 | - Make sure you have a [GitHub account](https://github.com/signup/free). 23 | - Create a topic branch from where you want to base your work. 24 | - Make sure _all_ tests are passing before you commit your changes. Use the `make check` command to do this. 25 | - Submit a pull request. 26 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) The Regents of the University of California. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 3. Neither the name of the University nor the names of its contributors 13 | may be used to endorse or promote products derived from this software 14 | without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ############## 2 | ## Please note 3 | ############## 4 | 5 | # First, run ``make install``. 6 | # After that you have through Makefile extension all the other base targets available. 7 | 8 | # If you want to release on GitHub, make sure to have a .env file with a GITHUB_TOKEN. 9 | # Also see: 10 | # https://github.com/settings/tokens 11 | # and https://github.com/release-it/release-it/blob/master/docs/github-releases.md#automated 12 | 13 | 14 | # Include base Makefile 15 | -include node_modules/@patternslib/dev/Makefile 16 | 17 | # Define the GITHUB_TOKEN in the .env file for usage with release-it. 18 | -include .env 19 | export 20 | 21 | PEGJS ?= npx pegjs 22 | SASS ?= npx sass 23 | YARN ?= npx yarn 24 | 25 | PACKAGE_NAME = "patternslib" 26 | 27 | all:: bundle css 28 | 29 | 30 | yarn.lock install: 31 | $(YARN) install 32 | 33 | 34 | .PHONY: watch 35 | watch: install 36 | $(YARN) watch 37 | 38 | 39 | .PHONY: build 40 | build: bundle css 41 | 42 | 43 | .PHONY: depends-parser 44 | depends-parser: install 45 | $(PEGJS) -O size -f es src/lib/depends_parse.pegjs 46 | 47 | 48 | # Unlink any linked dependencies before building a bundle. 49 | bundle-pre: 50 | -$(YARN) unlink @patternslib/dev 51 | -$(YARN) unlink @patternslib/pat-content-mirror 52 | -$(YARN) unlink @patternslib/pat-doclock 53 | -$(YARN) unlink @patternslib/pat-shopping-cart 54 | -$(YARN) unlink @patternslib/pat-sortable-table 55 | -$(YARN) unlink @patternslib/pat-tiptap 56 | -$(YARN) unlink @patternslib/pat-upload 57 | $(YARN) install --force 58 | 59 | 60 | .PHONY: css 61 | css: 62 | @$(SASS) -I style --load-path node_modules/ _sass/_patterns.scss style/patterns.css 63 | 64 | 65 | # Update patterns-site 66 | 67 | 68 | Patterns-site/Makefile: 69 | git clone git@github.com:Patternslib/Patterns-site.git 70 | 71 | 72 | .PHONY: update-patternslib-site 73 | update-patternslib-site: Patterns-site/Makefile 74 | # something 75 | cd Patterns-site && git pull && make update-patternslib && git push 76 | 77 | 78 | # Overrides release + Update https://patternslib.com 79 | 80 | 81 | .PHONY: release-major 82 | release-major: 83 | make LEVEL=major release 84 | make update-patternslib-site 85 | 86 | 87 | .PHONY: release-minor 88 | release-minor: 89 | make LEVEL=minor release 90 | make update-patternslib-site 91 | 92 | 93 | .PHONY: release-patch 94 | release-patch: 95 | make LEVEL=patch release 96 | make update-patternslib-site 97 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Making a release 2 | 3 | We are using release-it together with the conventional-changelog plugin for automatic changelog generation. 4 | Automatic changelog generation needs consistent commit messages wich follow th econventional commits format. 5 | A pre-commit hook checks for each commit message to conform to the specs. 6 | See our [code style guide](docs/developer/styleguide.md) for the changelog format. 7 | 8 | Make sure, you have a ``.env`` file with a ``GITHUB_TOKEN=...`` entry. 9 | This is used for the GitHub release which is created along with the npm release by ``make release-major``, ``make release-minor`` or ``make release-patch``. 10 | Also see: https://github.com/settings/tokens and https://github.com/release-it/release-it/blob/master/docs/github-releases.md#automated 11 | 12 | ## Release process 13 | 14 | - Run ``npm login`` to be able to push to the npm registry. 15 | - Run either of ``make release-major`` for major releases (e.g. 4.0.0), ``make release-minor`` for minor releases (e.g. 4.1.0) or ``make release-patch`` for patch releases (e.g. 4.0.1). 16 | This command runs ``make check``, runs ``release-it`` in dry run and if successful in real, generates the changelog, increases the package.json version, does a git tag, releases the package to npm and creates a zip file of the bundle which is published at the GitHub releases page. 17 | - Check: https://www.npmjs.com/package/@patternslib/patternslib 18 | - Check: https://github.com/Patternslib/Patterns/releases 19 | 20 | -------------------------------------------------------------------------------- /_sass/_fonts.scss: -------------------------------------------------------------------------------- 1 | // Patterns uses font based icons instead of images. Those are generated 2 | // with Fontello.com Make sure the fontello folder is placed in your 3 | // style folder 4 | 5 | @import "../style/fontello/css/fontello.css"; 6 | 7 | // Assets 8 | //@import url(http://fonts.googleapis.com/css?family=Sorts+Mill+Goudy:400,400italic); 9 | //@import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,700); 10 | // @import url(/style/fonts/font.css); 11 | // @import url(/style/fontello/fontello.css); 12 | -------------------------------------------------------------------------------- /_sass/_patterns.scss: -------------------------------------------------------------------------------- 1 | // Each pattern comes with a mixin. They may also be included seperately 2 | // in a project and applied on custom markup. 3 | 4 | @use "fonts"; 5 | @use "settings"; 6 | @use "mixins"; 7 | 8 | // Individual scss files are imported for each Pattern. These files may 9 | // also be imported seperately in a project, but always require the Patterns 10 | // mixins 11 | 12 | @use "components/avatar"; 13 | @use "components/button"; 14 | @use "components/button-bar"; 15 | @use "components/form"; 16 | @use "components/icon"; 17 | @use "../src/pat/auto-scale/auto-scale"; 18 | @use "../src/pat/auto-suggest/auto-suggest"; 19 | @use "../src/pat/carousel/carousel"; 20 | @use "../src/pat/checklist/checklist"; 21 | @use "../src/pat/collapsible/collapsible"; 22 | @use "../src/pat/colour-picker/colour-picker"; 23 | @use "../src/pat/date-picker/date-picker"; 24 | @use "../src/pat/datetime-picker/datetime-picker"; 25 | @use "../src/pat/equaliser/equaliser"; 26 | @use "../src/pat/expandable-tree/expandable-tree"; 27 | @use "../src/pat/focus/focus"; 28 | @use "../src/pat/gallery/gallery"; 29 | @use "../src/pat/grid/grid"; 30 | @use "../src/pat/image-crop/image-crop"; 31 | @use "../src/pat/inject/inject"; 32 | @use "../src/pat/inject/injection"; 33 | @use "../src/pat/masonry/masonry"; 34 | @use "../src/pat/menu/menu"; 35 | @use "../src/pat/modal/modal"; 36 | @use "../src/pat/notification/notification"; 37 | @use "../src/pat/sortable/sortable"; 38 | @use "../src/pat/stacks/stacks"; 39 | @use "../src/pat/switch/switch"; 40 | @use "../src/pat/syntax-highlight/syntax-highlight"; 41 | @use "../src/pat/toggle/toggle"; 42 | @use "../src/pat/tooltip/tooltip"; 43 | -------------------------------------------------------------------------------- /_sass/_settings.scss: -------------------------------------------------------------------------------- 1 | // Colours 2 | // $felt: #89AA74; 3 | $felt: #565656; 4 | 5 | $colour-accent: #0198e1 !default; 6 | $colour-base: #efefef !default; 7 | $colour-alert: red !default; 8 | $colour-success: green !default; 9 | $colour-notice: #ffffd6 !default; 10 | $colour-warning: orange !default; 11 | $colour-error: red !default; 12 | $colour-info: $colour-notice !default; 13 | 14 | // Font treatment 15 | $base-font-size: 18px; 16 | $base-line-height: 150%; 17 | $font-weight-normal: normal; 18 | $font-weight-bold: bold; 19 | 20 | // Glyphs 21 | $glyph-checkbox: "\e2002"; 22 | $glyph-checkbox-active: "\e2003"; 23 | $glyph-radio-button: "\e2000"; 24 | $glyph-radio-button-active: "\e2001"; 25 | $glyph-close: "\e2005"; 26 | 27 | // We use these to control various global styles 28 | $body-font-family: "Source Sans Pro", sans-serif; 29 | $body-font-weight: $font-weight-normal; 30 | $body-font-style: normal; 31 | 32 | // Categories 33 | $cat-behavioural: #717dd7; 34 | $cat-fancy-stuff: #bf9230; 35 | $cat-form: #be9ac1; 36 | $cat-layout: #a1ced2; 37 | 38 | // Responsive variables 39 | 40 | $break-small: 768px !default; 41 | $break-large: 769px !default; 42 | -------------------------------------------------------------------------------- /_sass/components/_avatar.scss: -------------------------------------------------------------------------------- 1 | @use "../mixins"; 2 | 3 | .pat-avatar { 4 | @include mixins.pat-avatar(); 5 | } 6 | -------------------------------------------------------------------------------- /_sass/components/_button-bar.scss: -------------------------------------------------------------------------------- 1 | .pat-button-bar { 2 | margin-bottom: 1em; 3 | } 4 | -------------------------------------------------------------------------------- /_sass/components/_icon.scss: -------------------------------------------------------------------------------- 1 | .iconified { 2 | overflow: hidden; 3 | text-decoration: none; 4 | position: relative; 5 | display: inline-block; 6 | white-space: nowrap; 7 | line-height: 10px; 8 | border-style: none; 9 | background-image: none; 10 | filter: none !important; 11 | outline: none !important; 12 | width: 1.3em; 13 | &:active { 14 | box-shadow: none; 15 | } 16 | &:hover { 17 | text-decoration: none; 18 | } 19 | &:before { 20 | text-indent: 0; 21 | display: inline-block; 22 | margin: 0 10px 0 0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /_sass/components/_photoswipe.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/_sass/components/_photoswipe.scss -------------------------------------------------------------------------------- /_sass/components/_tiny-content.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/_sass/components/_tiny-content.scss -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require("@patternslib/dev/babel.config.js"); 2 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require("@patternslib/dev/commitlint.config.js"); 2 | -------------------------------------------------------------------------------- /docs/designer/markup-styleguide.md: -------------------------------------------------------------------------------- 1 | # The Markup styleguide 2 | -------------------------------------------------------------------------------- /docs/designer/tips-and-tricks.md: -------------------------------------------------------------------------------- 1 | # Tips and tricks when using patterns 2 | 3 | ## You can disable patterns by changing the URL 4 | 5 | When working with patterns, it might be useful to selectively disable 6 | certain patterns. 7 | 8 | You can easily do this by adding the `patterns-disable` parameter to the query string 9 | of the URL you are on. 10 | 11 | For example, if you'd like to disable the `toggle` pattern, then add 12 | `?patterns-disable=toggle` to your URLs query string. 13 | -------------------------------------------------------------------------------- /docs/designer/what-is-patternslib.md: -------------------------------------------------------------------------------- 1 | # What is Patternslib? 2 | 3 | Patternslib is a library of reusable patterns which let you create rich, dynamic and interactive prototypes or websites, without having to know or care about Javascript. 4 | 5 | Instead of writing or integrating Javascript, you simply add special CSS classes and HTML5 data attributes to your HTML. 6 | These classes and `data-` attributes describe and invoke the so-called "interaction patterns" of Patternslib which add rich functionality to your page. 7 | 8 | Patternslib is both a library of reusable interaction patterns as well as a small framework for creating such patterns. 9 | -------------------------------------------------------------------------------- /docs/developer/usage-recipies.md: -------------------------------------------------------------------------------- 1 | # Using require.js to load your custom pattern 2 | 3 | ## Using the bundle 4 | 5 | If you are using a precompiled bundle with require.js, then the following approach is appropriate: 6 | 7 | You should have an entry point for `require.js` in this example `main.js`. So your html will contain: 8 | 9 | ``` 10 | 11 | ``` 12 | 13 | In your `main.js`, you should define the `registry` module pointing to the bundle as well as any custom modules. 14 | For the sake of simplicity we assume here that there is only one additional module defined that adds a custom pattern. 15 | 16 | So our `main.js` looks like: 17 | 18 | ``` 19 | require.config({ 20 | paths: { 21 | registry: 'bundle', 22 | custom: 'custom' 23 | }, 24 | }); 25 | define(['registry', 'custom'], function (registry, custom) { 26 | console.log(registry); 27 | console.log(custom); 28 | console.log(registry.patterns.custom); 29 | }); 30 | ``` 31 | 32 | ## Without using the bundle 33 | 34 | Not using the bundle, allows you to select patterns individually and gives you a bit more flexibility. 35 | For this example we will assume that you want only the `ajax` pattern as well as the custom pattern defined in the previous section. 36 | 37 | In this case, you will need to explicitly give the paths to all the modules you need. 38 | In the case of the `ajax` pattern we depend on `jquery`, `jquery.form`, `logging`, `parser`, `utils`, `compat`, `jquery-ext`, `registry`. 39 | 40 | Your `main.js` will look similar to: 41 | 42 | ``` 43 | require.config({ 44 | 45 | paths: { 46 | jquery: 'jquery', 47 | logging: 'logging', 48 | 'jquery.form': 'jquery.form', 49 | 50 | parser: 'patterns_dir/core/parser', 51 | utils: 'patterns_dir/core/utils', 52 | 'jquery-ext': 'patterns_dir/core/jquery-ext', 53 | 54 | registry: 'patterns_dir/core/registry', 55 | ajax: 'patterns_dir/pat/ajax', 56 | 57 | custom: 'custom' 58 | } 59 | }); 60 | 61 | define(['registry', 'ajax', 'custom'], function (registry, ajax, custom) { 62 | console.log(registry); 63 | console.log(ajax); 64 | console.log(custom); 65 | console.log(registry.patterns.custom); 66 | }); 67 | ``` 68 | -------------------------------------------------------------------------------- /docs/history/index.md: -------------------------------------------------------------------------------- 1 | # History 2 | 3 | The changelog of previous Patternslib releases. 4 | 5 | - [Changelog of Version 8](8.md) 6 | - [Changelog of Version 7](7.md) 7 | - [Changelog of Version 6](6.md) 8 | - [Changelog of Version 5](5.md) 9 | - [Changelog of Version 4](4.md) 10 | - [Changelog of Version 3](3.md) 11 | - [Changelog of Version 2](2.md) 12 | - [Changelog of Version 1](1.md) 13 | 14 | -------------------------------------------------------------------------------- /eslint.config.js: -------------------------------------------------------------------------------- 1 | const config_eslint = require("@patternslib/dev/eslint.config.js"); 2 | 3 | module.exports = [ 4 | ...config_eslint, 5 | { 6 | ignores: [ 7 | // Ignore auto-generated depends_parse.js file. 8 | "src/lib/depends_parse.js", 9 | ], 10 | }, 11 | ] 12 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const config = require("@patternslib/dev/jest.config.js"); 3 | 4 | config.setupFilesAfterEnv.push(path.resolve(__dirname, "./src/setup-tests.js")); 5 | config.moduleNameMapper["@patternslib/patternslib/(.*)"] = 6 | path.resolve(__dirname) + "/$1"; 7 | 8 | module.exports = config; 9 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require("@patternslib/dev/prettier.config.js"); 2 | -------------------------------------------------------------------------------- /src/core/basepattern.md: -------------------------------------------------------------------------------- 1 | # BasePattern base pattern class. 2 | 3 | A Base pattern for creating scoped patterns. 4 | 5 | Each instance of a pattern has its own local scope. 6 | A new instance is created for each DOM element on which a pattern applies. 7 | 8 | 9 | ## Usage: 10 | 11 | Also see: https://github.com/Patternslib/pat-PATTERN_TEMPLATE 12 | 13 | 14 | import { BasePattern } from "@patternslib/patternslib/src/core/basepattern"; 15 | import Parser from "@patternslib/patternslib/src/core/parser"; 16 | import registry from "@patternslib/patternslib/src/core/registry"; 17 | 18 | export const parser = new Parser("test-pattern"); 19 | parser.addArgument("example-option", "Stranger"); 20 | 21 | class Pattern extends BasePattern { 22 | static name = "test-pattern"; 23 | static trigger = ".pat-test-pattern"; 24 | static parser = parser; 25 | 26 | async init() { 27 | import("./test-pattern.scss"); 28 | 29 | // Try to avoid jQuery, but here is how to import it. 30 | // eslint-disable-next-line no-unused-vars 31 | const $ = (await import("jquery")).default; 32 | 33 | // The options are automatically created, if parser is defined. 34 | const example_option = this.options.exampleOption; 35 | this.el.innerHTML = ` 36 |

hello, ${example_option}, this is pattern ${this.name} speaking.

37 | `; 38 | } 39 | } 40 | 41 | // Register Pattern class in the global pattern registry 42 | registry.register(Pattern); 43 | 44 | // Make it available 45 | export default Pattern; 46 | 47 | -------------------------------------------------------------------------------- /src/core/feature-detection.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | // Add JavaScript feature as class to the element, just like 3 | // Modernizr does. This is needed for accessibility reasons, to support 4 | // browsers and situations where JavaScript is not available or disabled. 5 | // The HTML root tag needs to have the `no-js` class set which is then 6 | // replaced by `js`. 7 | const html = document.getElementsByTagName("html")[0]; 8 | if (html.classList.contains("no-js")) { 9 | html.classList.remove("no-js"); 10 | html.classList.add("js"); 11 | } 12 | 13 | // NOTE: Modernizr will be removed in an upcoming minor release. 14 | 15 | // Do not load modernizr if disabled. It's enabled by default. 16 | // You might want to disable it for your project by setting: 17 | // window.__patternslib_disable_modernizr = true; 18 | if (window.__patternslib_disable_modernizr) { 19 | return; 20 | } 21 | 22 | // Get the current script tag's URL. 23 | const script_url = document.currentScript.src; 24 | // Get the base URL of the current script tag's URL. 25 | let base_url = script_url.substring(0, script_url.lastIndexOf("/")) + "/"; 26 | // The modernizr script is located outside the chunks directory. 27 | base_url = base_url.replace("chunks/", ""); 28 | 29 | // Inject a new one with the modernizr bundle. 30 | const script_tag = document.createElement("script"); 31 | script_tag.src = base_url + "modernizr.min.js"; 32 | document.getElementsByTagName("head")[0].appendChild(script_tag); 33 | })(); 34 | -------------------------------------------------------------------------------- /src/core/feature-detection.md: -------------------------------------------------------------------------------- 1 | # Feature detection 2 | 3 | This module adds the `js` class to the HTML root node and loads Modernizr for more feature detection. 4 | 5 | --- 6 | ** Note ** 7 | 8 | If you create own bundles based on Patternslib, you would need to import the `src/core/feature-detection` module for these features to be available. 9 | 10 | --- 11 | 12 | 13 | ## Adding the "js" class for accessibility styles 14 | 15 | There are situations where web browsers do not have JavaScript available or when it is disabled. 16 | In situations where no JavaScript is available you might want to show certain elements where in JavaScript situations you might want to hide them until a JavaScript functionality is showing them. 17 | 18 | In the Media Query Level 5 specification there is a CSS media feature to detect JavaScript via a [`scripting` at-rule](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/scripting). 19 | But at time of this writing this is [not available in any of the major browsers](https://caniuse.com/mdn-css_at-rules_media_scripting). 20 | 21 | Therefore Patternslib adds a `js` class to the HTML root node, if the HTML root node already has a `no-js` class. 22 | The `js` class is set very early before any browser layout is done if you include the Patternslib script in the HEAD of your site. 23 | 24 | Markup: 25 | 26 | ``` 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ``` 35 | 36 | When the JavaScript is loaded, the `no-js` class is removed and the `js` class is set: 37 | 38 | ``` 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | ``` 47 | 48 | 49 | ## Loading Modernizr 50 | 51 | Modernizr is loaded for more feature detection. 52 | 53 | To disable Modernizr you can set `window.__patternslib_disable_modernizr = true;` just before you load the Patternslib bundle: 54 | 55 | ``` 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | ``` 65 | 66 | --- 67 | ** Note ** 68 | 69 | The Modernizr feature detection is being phased out and might be removed in a future version of Patternslib. 70 | 71 | --- 72 | -------------------------------------------------------------------------------- /src/core/i18n.js: -------------------------------------------------------------------------------- 1 | /* This is a stub, used by patterns that need compatibility with Mockup which 2 | * have i18n support. 3 | * 4 | * Eventually we might want to implement our own i18n functionality here (while 5 | * keeping compatibility with Mockup). 6 | * 7 | * Jed.js would be a good candidate. (http://slexaxton.github.io/Jed) 8 | */ 9 | 10 | export default function translate(str) { 11 | return str; 12 | } 13 | -------------------------------------------------------------------------------- /src/core/jquery-ext.test.js: -------------------------------------------------------------------------------- 1 | import "./jquery-ext"; 2 | import $ from "jquery"; 3 | 4 | describe("Find including top-level elements", function () { 5 | it("Top-level elements are included", function () { 6 | var $col = $( 7 | "
" + 8 | "

" + 9 | "" + 10 | "
" + 11 | "
" + 12 | "

" 13 | ), 14 | $match = $col.findInclusive("div p"); 15 | expect($match.length).toBe(1); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /src/core/mockup-parser.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | 3 | var parser = { 4 | getOptions($el, patternName, options) { 5 | /* This is the Mockup parser. An alternative parser for Patternslib 6 | * patterns. 7 | * 8 | * NOTE: Use of the Mockup parser is discouraged and is added here for 9 | * legacy support for the Plone Mockup project. 10 | * 11 | * It parses a DOM element for pattern configuration options. 12 | */ 13 | options = options || {}; 14 | // get options from parent element first, stop if element tag name is 'body' 15 | if ($el.length !== 0 && !$.nodeName($el[0], "body")) { 16 | options = this.getOptions($el.parent(), patternName, options); 17 | } 18 | // collect all options from element 19 | let elOptions = {}; 20 | if ($el.length !== 0) { 21 | elOptions = $el.data("pat-" + patternName); 22 | if (elOptions) { 23 | // parse options if string 24 | if (typeof elOptions === "string") { 25 | const tmpOptions = {}; 26 | $.each(elOptions.split(";"), function (i, item) { 27 | item = item.split(":"); 28 | item.reverse(); 29 | let key = item.pop(); 30 | key = key.replace(/^\s+|\s+$/g, ""); // trim 31 | item.reverse(); 32 | let value = item.join(":"); 33 | value = value.replace(/^\s+|\s+$/g, ""); // trim 34 | tmpOptions[key] = value; 35 | }); 36 | elOptions = tmpOptions; 37 | } 38 | } 39 | } 40 | return $.extend(true, {}, options, elOptions); 41 | }, 42 | }; 43 | 44 | export default parser; 45 | -------------------------------------------------------------------------------- /src/core/polyfills.test.js: -------------------------------------------------------------------------------- 1 | import "./polyfills"; 2 | 3 | describe("NavigateEvent tests", () => { 4 | afterEach(() => { 5 | document.body.innerHTML = ""; 6 | }); 7 | 8 | it("should fire an event when history.pushState is called.", () => { 9 | let destination_url; 10 | 11 | window.navigation.addEventListener("navigate", (event) => { 12 | destination_url = event.destination.url; 13 | }); 14 | 15 | const path = "foo/bar/baz.html"; 16 | history.pushState(null, "", path); 17 | 18 | expect(destination_url).toBe(path); 19 | }); 20 | 21 | 22 | it("should fire an event when history.replaceState is called.", () => { 23 | let destination_url; 24 | 25 | window.navigation.addEventListener("navigate", (event) => { 26 | destination_url = event.destination.url; 27 | }); 28 | 29 | const path = "foo/bar/baz.html"; 30 | history.replaceState(null, "", path); 31 | 32 | expect(destination_url).toBe(path); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /src/core/remove.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Patterns remove - send event when objects are removed from the DOM 3 | * 4 | * Copyright 2012 Simplon B.V. - Wichert Akkerman 5 | */ 6 | import $ from "jquery"; 7 | 8 | var real_cleanData = $.cleanData; 9 | 10 | $.cleanData = function remove_cleanData(elems) { 11 | var i, el; 12 | for (i = 0; (el = elems[i]) !== undefined; i++) $(el).triggerHandler("destroy"); 13 | real_cleanData.call(this, arguments); 14 | }; 15 | -------------------------------------------------------------------------------- /src/core/url.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Patterns URL - URL parsing utilities 3 | * 4 | * Copyright 2013 Simplon B.V. 5 | */ 6 | 7 | function UrlArgumentParser() { 8 | this._cache = null; 9 | if (window.addEventListener) window.addEventListener("popstate", this._reset); 10 | } 11 | 12 | UrlArgumentParser.prototype = { 13 | space_pattern: /\+/g, 14 | keyvalue_pattern: /^(.+?)(?:=(.*))/, 15 | 16 | _reset: function UrlArgumentParser_reset() { 17 | this._cache = null; 18 | }, 19 | 20 | _decodeQS: function UrlArgumentParser_decodeQS(bit) { 21 | return decodeURIComponent(bit.replace(this.space_pattern, " ")); 22 | }, 23 | 24 | _parse: function UrlArgumentParser_parse(qs) { 25 | var query = /\?(.+)/.exec(qs), 26 | params = {}; 27 | 28 | if (query === null) return params; 29 | 30 | var parameters = query[1].split("&"), 31 | i, 32 | parts, 33 | key, 34 | value; 35 | 36 | for (i = 0; i < parameters.length; i++) { 37 | if ((parts = this.keyvalue_pattern.exec(parameters[i])) === null) { 38 | key = this._decodeQS(parameters[i]); 39 | value = null; 40 | } else { 41 | key = this._decodeQS(parts[1]); 42 | value = this._decodeQS(parts[2]); 43 | } 44 | 45 | if (params[key] === undefined) params[key] = []; 46 | params[key].push(value); 47 | } 48 | 49 | return params; 50 | }, 51 | 52 | get: function UrlArgumentParser_get() { 53 | if (this._cache === null) this._cache = this._parse(window.location.search); 54 | return this._cache; 55 | }, 56 | }; 57 | 58 | var url_parser = new UrlArgumentParser(); 59 | 60 | export default { 61 | UrlArgumentParser: UrlArgumentParser, 62 | parameters: url_parser.get.bind(url_parser), 63 | }; 64 | -------------------------------------------------------------------------------- /src/core/url.test.js: -------------------------------------------------------------------------------- 1 | import url from "./url"; 2 | 3 | describe("Core / url / UrlArgumentParser", function () { 4 | describe("_decodeQS", function () { 5 | it("Basic string", function () { 6 | var parser = new url.UrlArgumentParser(); 7 | expect(parser._decodeQS("Foo")).toBe("Foo"); 8 | }); 9 | 10 | it("String with whitespace", function () { 11 | var parser = new url.UrlArgumentParser(); 12 | expect(parser._decodeQS("Aap+Noot+Mies")).toBe("Aap Noot Mies"); 13 | }); 14 | 15 | it("String with encoded characters", function () { 16 | var parser = new url.UrlArgumentParser(); 17 | expect(parser._decodeQS("Jip%26Janneke")).toBe("Jip&Janneke"); 18 | }); 19 | }); 20 | 21 | describe("_parse", function () { 22 | it("No query string", function () { 23 | var parser = new url.UrlArgumentParser(); 24 | expect(parser._parse("")).toEqual({}); 25 | }); 26 | 27 | it("No parameter specified", function () { 28 | var parser = new url.UrlArgumentParser(); 29 | expect(parser._parse("?")).toEqual({}); 30 | }); 31 | 32 | it("Parameter without value", function () { 33 | var parser = new url.UrlArgumentParser(); 34 | expect(parser._parse("?key")).toEqual({ key: [null] }); 35 | }); 36 | 37 | it("Parameter with empty value", function () { 38 | var parser = new url.UrlArgumentParser(); 39 | expect(parser._parse("?key=")).toEqual({ key: [""] }); 40 | }); 41 | 42 | it("Parameter with plain value", function () { 43 | var parser = new url.UrlArgumentParser(); 44 | expect(parser._parse("?key=value")).toEqual({ key: ["value"] }); 45 | }); 46 | 47 | it("Multiple parameters", function () { 48 | var parser = new url.UrlArgumentParser(); 49 | expect(parser._parse("?one=en&two=to")).toEqual({ 50 | one: ["en"], 51 | two: ["to"], 52 | }); 53 | }); 54 | 55 | it("Parameter with multiple values", function () { 56 | var parser = new url.UrlArgumentParser(); 57 | expect(parser._parse("?key=value&key=other")).toEqual({ 58 | key: ["value", "other"], 59 | }); 60 | }); 61 | }); 62 | }); 63 | 64 | describe("Core / url / parameters", function () { 65 | it("Bound to working parser", function () { 66 | expect(url.parameters()).not.toBe(undefined); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /src/core/uuid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Get a universally unique id (uuid). 3 | * 4 | * @returns {String} - The uuid. 5 | */ 6 | const create_uuid = () => { 7 | let uuid; 8 | if (window.crypto.randomUUID) { 9 | // Create a real UUID 10 | // window.crypto.randomUUID does only exist in browsers with secure 11 | // context. 12 | // See: https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID 13 | uuid = window.crypto.randomUUID(); 14 | } else { 15 | // Create a sufficiently unique ID 16 | const array = new Uint32Array(4); 17 | uuid = window.crypto.getRandomValues(array).join(""); 18 | } 19 | return uuid; 20 | }; 21 | export default create_uuid; 22 | -------------------------------------------------------------------------------- /src/core/uuid.test.js: -------------------------------------------------------------------------------- 1 | import create_uuid from "./uuid"; 2 | 3 | describe("uuid", function () { 4 | it("returns a UUIDv4", function () { 5 | const uuid = create_uuid(); 6 | expect(uuid).toMatch( 7 | /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/ 8 | ); 9 | }); 10 | 11 | it("returns a sufficiently unique id", function () { 12 | // Mock window.crypto.randomUUID not existing, like in browser with 13 | // non-secure context. 14 | const orig_randomUUID = window.crypto.randomUUID; 15 | window.crypto.randomUUID = undefined; 16 | 17 | const uuid = create_uuid(); 18 | expect(uuid).toMatch(/^[0-9]*$/); 19 | 20 | window.crypto.randomUUID = orig_randomUUID; 21 | }); 22 | 23 | it("the uuid is unique", function () { 24 | expect(create_uuid()).not.toBe(create_uuid()); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Load modernizr and the `html.js` feature class. 2 | // NOTE: Modernizr will be removed in an upcoming minor release. 3 | import "./core/feature-detection"; 4 | 5 | // Webpack entry point for module federation. 6 | import "@patternslib/dev/webpack/module_federation"; 7 | 8 | // The next import needs to be kept with parentheses, otherwise we get this error: 9 | // "Shared module is not available for eager consumption." 10 | import("./patterns"); 11 | 12 | // Register jQuery gloablly as soon as this script is executed. 13 | async function register_global_libraries() { 14 | const jquery = (await import("jquery")).default; 15 | window.jQuery = jquery; 16 | window.$ = jquery; 17 | } 18 | register_global_libraries(); 19 | -------------------------------------------------------------------------------- /src/pat/auto-scale/_auto-scale.scss: -------------------------------------------------------------------------------- 1 | .pat-auto-scale { 2 | -moz-transform-origin: left top; 3 | -webkit-transform-origin: left top; 4 | transform-origin: left top; 5 | opacity: 0; 6 | -moz-transition: opacity 0.2s; 7 | -webkit-transition: opacity 0.2s; 8 | transition: opacity 0.2s; 9 | } 10 | 11 | .pat-auto-scale.scaled { 12 | opacity: 1; 13 | } 14 | -------------------------------------------------------------------------------- /src/pat/auto-submit/pattern-test-response.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Feedback 5 | 6 | 7 | 8 |

Succeeded!!

10 | 11 | 12 | -------------------------------------------------------------------------------- /src/pat/auto-submit/placeholder.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/auto-submit/placeholder.gif -------------------------------------------------------------------------------- /src/pat/auto-suggest/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "id": "john-snow", "text": "John Snow" }, 3 | { "id": "tywin-lannister", "text": "Tywin Lannister" }, 4 | { "id": "mary-rose", "text": "Mary Rose" }, 5 | { "id": "joe-black", "text": "Joe Black" } 6 | ] 7 | -------------------------------------------------------------------------------- /src/pat/auto-suggest/datagroup.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Fruits", 4 | "children": [ 5 | { 6 | "id": 1, 7 | "text": "Apples" 8 | }, 9 | { 10 | "id": 2, 11 | "text": "Pears" 12 | } 13 | ] 14 | }, 15 | { 16 | "text": "Vegetables", 17 | "children": [ 18 | { 19 | "id": 3, 20 | "text": "Salad" 21 | }, 22 | { 23 | "id": 4, 24 | "text": "Onion" 25 | } 26 | ] 27 | } 28 | ] 29 | -------------------------------------------------------------------------------- /src/pat/auto-suggest/select2-spinner.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/auto-suggest/select2-spinner.gif -------------------------------------------------------------------------------- /src/pat/auto-suggest/select2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/auto-suggest/select2.png -------------------------------------------------------------------------------- /src/pat/auto-suggest/select2x2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/auto-suggest/select2x2.png -------------------------------------------------------------------------------- /src/pat/autofocus/autofocus.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | import { BasePattern } from "../../core/basepattern"; 3 | import dom from "../../core/dom"; 4 | import registry from "../../core/registry"; 5 | 6 | let scheduled_task = null; 7 | 8 | class Pattern extends BasePattern { 9 | static name = "autofocus"; 10 | static trigger = ` 11 | input.pat-autofocus, 12 | input[autofocus], 13 | select.pat-autofocus, 14 | select[autofocus], 15 | textarea.pat-autofocus, 16 | textarea[autofocus], 17 | button.pat-autofocus, 18 | button[autofocus] 19 | `; 20 | 21 | init() { 22 | if (window.self !== window.top) { 23 | // Do not autofocus in iframes. 24 | return; 25 | } 26 | 27 | // Re-focus after relevant DOM changes. 28 | $(document).on("pat-update", (e, data) => { 29 | const updated = data?.dom; 30 | if (updated?.contains(this.el)) { 31 | // Only focus if the updated element is a parent of this autofocus element. 32 | this.set_focus(); 33 | } 34 | }); 35 | 36 | this.set_focus(); 37 | } 38 | 39 | set_focus() { 40 | if (dom.is_visible(this.el) && this.el.value === "") { 41 | // Set autofocus only for visible and empty inputs. 42 | 43 | // Clear scheduled tasks if there are any. 44 | // Note: Patterns scanning initizlizes patterns "inside-out", so 45 | // DOM nodes later in the tree are initizlized first. 46 | // With multiple pattern instantiations and then module- 47 | // globally clearing and re-scheduling tasks we are 48 | // initializing in the end the first pattern which matches 49 | // the conditions. 50 | clearTimeout(scheduled_task); 51 | scheduled_task = setTimeout(() => { 52 | this.el.focus(); 53 | scheduled_task = null; 54 | }, 100); 55 | } 56 | } 57 | } 58 | 59 | registry.register(Pattern); 60 | 61 | export default Pattern; 62 | export { Pattern }; 63 | -------------------------------------------------------------------------------- /src/pat/autofocus/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | With the Autofocus pattern you may choose which input field gets the focus when a page is loaded or injected. 4 | 5 | 6 | ## Documentation 7 | 8 | Patterns augments the standard HTML5 autofocus behaviour. 9 | 10 | On initial page load or when new content is injected it is scanned for input elements with an `autofocus` attribute or `pat-autofocus` class. 11 | 12 | The first such element that has no current value will be given the focus. 13 | 14 |
15 | 16 | 17 |
18 | 19 | In this example the keywords input field would be given the focus since the title field already has a value. 20 | -------------------------------------------------------------------------------- /src/pat/autofocus/index-iframed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pat-autofocus iframe'd demo page 5 | 6 | 7 | 8 | 9 | 10 |
11 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /src/pat/autofocus/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pat-autofocus demo page 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 | 18 |
19 | 25 |
26 | 32 | 33 |

Input 4 - should get focus when collapsible is opened.

34 |
35 |

Open collapsible.

36 | 37 | 38 |
39 | 40 |

Input 5 - inject element with autofocus.

41 | inject autofocus input here 44 | 45 |
46 |
47 | 48 |

Elements in the iframe below should not get the focus.

49 | 53 | 54 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/pat/calendar/test_event.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test event 5 | 6 | 7 | 8 |
9 | hello i'm some detail infor for a test event 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/pat/calendar/test_event_source.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "title": "Event 1", 5 | "start": "2020-10-10T16:00:00", 6 | "end": "2020-10-10T18:00:00", 7 | "class": "hello-class-1 hello-class-2 calendar-section1-category1", 8 | "@id": "./test_event.html" 9 | }, 10 | { 11 | "title": "Event 2", 12 | "start": "2020-10-12", 13 | "end": "2020-10-12", 14 | "class": "calendar-section1-category2", 15 | "@id": "./test_event.html" 16 | }, 17 | { 18 | "title": "Event 3", 19 | "start": "2020-10-14", 20 | "end": "2020-10-16", 21 | "class": "calendar-section2-category1" 22 | }, 23 | { 24 | "title": "Event 4", 25 | "start": "2020-11-01", 26 | "end": "2020-11-02", 27 | "color": "green", 28 | "class": "calendar-section2-category1" 29 | }, 30 | { 31 | "title": "Event 5", 32 | "start": "2020-11-04", 33 | "end": "2020-11-05", 34 | "color": "#00FFFF", 35 | "class": "calendar-section1-category1 calendar-section2-category1" 36 | }, 37 | { 38 | "title": "Event 6", 39 | "start": "2020-11-08", 40 | "end": "2020-11-10", 41 | "color": "#AAAAAA", 42 | "class": "calendar-section1-category2 calendar-section2-category2" 43 | } 44 | ] 45 | } 46 | -------------------------------------------------------------------------------- /src/pat/calendar/test_event_source2.json: -------------------------------------------------------------------------------- 1 | { 2 | "items": [ 3 | { 4 | "title": "Calendar 2 Event 1", 5 | "start": "2020-10-08T10:00:00", 6 | "end": "2020-10-08T12:00:00", 7 | "color": "orange", 8 | "class": "calendar-section1-category1" 9 | }, 10 | { 11 | "title": "Calendar 2 Event 2", 12 | "start": "2020-10-09T10:00:00", 13 | "end": "2020-10-09T12:00:00", 14 | "color": "yellow", 15 | "class": "calendar-section1-category2" 16 | }, 17 | { 18 | "title": "Calendar 2 Event 3", 19 | "start": "2020-10-08T00:00:00", 20 | "end": "2020-10-10T23:59:59", 21 | "color": "green", 22 | "class": "calendar-section2-category1" 23 | }, 24 | { 25 | "title": "Calendar 2 Event 4", 26 | "start": "2020-11-16T10:00:00", 27 | "end": "2020-11-16T12:00:00", 28 | "color": "orange", 29 | "class": "calendar-section2-category1" 30 | }, 31 | { 32 | "title": "Calendar 2 Event 5", 33 | "start": "2020-11-20T10:00:00", 34 | "end": "2020-11-20T12:00:00", 35 | "color": "yellow", 36 | "class": "calendar-section1-category1 calendar-section2-category1" 37 | }, 38 | { 39 | "title": "Calendar 2 Event 6", 40 | "start": "2020-11-25T10:00:00", 41 | "end": "2020-11-25T12:00:00", 42 | "color": "grey", 43 | "class": "calendar-section1-category2 calendar-section2-category2" 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /src/pat/carousel/_carousel.scss: -------------------------------------------------------------------------------- 1 | /* Slider */ 2 | .slick-slider { 3 | position: relative; 4 | 5 | display: block; 6 | box-sizing: border-box; 7 | 8 | -webkit-user-select: none; 9 | -moz-user-select: none; 10 | -ms-user-select: none; 11 | user-select: none; 12 | 13 | -webkit-touch-callout: none; 14 | -khtml-user-select: none; 15 | -ms-touch-action: pan-y; 16 | touch-action: pan-y; 17 | -webkit-tap-highlight-color: transparent; 18 | } 19 | 20 | .slick-list { 21 | position: relative; 22 | 23 | display: block; 24 | overflow: hidden; 25 | 26 | margin: 0; 27 | padding: 0; 28 | } 29 | .slick-list:focus { 30 | outline: none; 31 | } 32 | .slick-list.dragging { 33 | cursor: pointer; 34 | cursor: hand; 35 | } 36 | 37 | .slick-slider .slick-track, 38 | .slick-slider .slick-list { 39 | -webkit-transform: translate3d(0, 0, 0); 40 | -moz-transform: translate3d(0, 0, 0); 41 | -ms-transform: translate3d(0, 0, 0); 42 | -o-transform: translate3d(0, 0, 0); 43 | transform: translate3d(0, 0, 0); 44 | } 45 | 46 | .slick-track { 47 | position: relative; 48 | top: 0; 49 | left: 0; 50 | 51 | display: block; 52 | margin-left: auto; 53 | margin-right: auto; 54 | } 55 | .slick-track:before, 56 | .slick-track:after { 57 | display: table; 58 | 59 | content: ""; 60 | } 61 | .slick-track:after { 62 | clear: both; 63 | } 64 | .slick-loading .slick-track { 65 | visibility: hidden; 66 | } 67 | 68 | .slick-slide { 69 | display: none; 70 | float: left; 71 | 72 | height: 100%; 73 | min-height: 1px; 74 | } 75 | [dir="rtl"] .slick-slide { 76 | float: right; 77 | } 78 | .slick-slide img { 79 | display: block; 80 | } 81 | .slick-slide.slick-loading img { 82 | display: none; 83 | } 84 | .slick-slide.dragging img { 85 | pointer-events: none; 86 | } 87 | .slick-initialized .slick-slide { 88 | display: block; 89 | } 90 | .slick-loading .slick-slide { 91 | visibility: hidden; 92 | } 93 | .slick-vertical .slick-slide { 94 | display: block; 95 | 96 | height: auto; 97 | 98 | border: 1px solid transparent; 99 | } 100 | .slick-arrow.slick-hidden { 101 | display: none; 102 | } 103 | -------------------------------------------------------------------------------- /src/pat/carousel/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/carousel/ajax-loader.gif -------------------------------------------------------------------------------- /src/pat/carousel/carousel-arrows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/carousel/carousel-arrows.png -------------------------------------------------------------------------------- /src/pat/carousel/carousel-arrows.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/carousel/carousel-arrows.psd -------------------------------------------------------------------------------- /src/pat/checklist/_checklist.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | @use "../../../_sass/settings"; 3 | 4 | .pat-checklist { 5 | > br { 6 | display: none; 7 | } 8 | 9 | &, 10 | label { 11 | padding-left: 1.5em; 12 | position: relative; 13 | display: block; 14 | 15 | &.checked:before, 16 | &.unchecked:before { 17 | font-family: fontello; 18 | content: "#{settings.$glyph-checkbox}"; 19 | float: left; 20 | position: absolute; 21 | left: 0; 22 | top: 0em; 23 | } 24 | 25 | &.checked:before { 26 | content: "#{settings.$glyph-checkbox-active}"; 27 | } 28 | 29 | input[type="checkbox"], 30 | input[type="radio"] { 31 | opacity: 0; 32 | position: absolute; 33 | } 34 | } 35 | 36 | &.radio label { 37 | &:before { 38 | content: "#{settings.$glyph-radio-button}"; 39 | } 40 | &.checked:before { 41 | content: "#{settings.$glyph-radio-button-active}"; 42 | } 43 | } 44 | 45 | fieldset.composed { 46 | padding-left: 0; 47 | margin-bottom: 0; 48 | position: relative; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/pat/clone-code/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Copy part of the DOM tree and show it as code. 4 | 5 | 6 | ## Documentation 7 | 8 | The clone-code copies a part of the DOM tree and wraps it in a `
` structure as plain text.
 9 | 
10 | This pattern is especially useful when writing interactive documentation and showing the code at the same time.
11 | 
12 | 
13 | ### Usage
14 | 
15 | This pattern is enabled by adding the `pat-clone` class on a container element which contains the original element and any clones of it that may have beeen added.
16 | The first element inside the .pat-clone container is by default assumed to be the original element may be cloned by the user.
17 | 
18 |     
19 |

Hello.

20 |
21 | 22 | This will result in: 23 | 24 |
25 |       
26 |         <p>Hello.</p>
27 |       
28 |     
29 | 30 | 31 | ### Excluding markup from copying 32 | 33 | You can exclude markup from copying by adding the `clone-code` class to it. 34 | If that class is present, the whole `clone-code` markup subtree is ignored. 35 | 36 | 37 | ### Option reference 38 | 39 | | Property | Description | Default | Type | 40 | | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------- | --------------------------------- | 41 | | source | CSS selector to define the source from where the markup should be copied. | :first-child | CSS Selector | 42 | | features | List of features to activate. Currently only `format` is implemented. Format does prettify the HTML markup with the library `prettier`. | null | Comma seperated list of strings. | 43 | 44 | -------------------------------------------------------------------------------- /src/pat/clone-code/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pat-clone demo page 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |

Clone Code

13 | 14 |

Example 1

15 | 16 |

17 | Clone the next block and ignore this paragraph which has the `clone-ignore` class. 18 |

19 | 20 |
21 |

Hello.

22 |
23 | 24 |

Example 2

25 | 26 |

27 | Clone the whole HTML page but ignore this paragraph which has the `clone-ignore` class. 28 |

29 | 30 |
32 |

Test paragraph

33 |
34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/pat/close-panel/close-panel.js: -------------------------------------------------------------------------------- 1 | import Base from "../../core/base"; 2 | import events from "../../core/events"; 3 | import utils from "../../core/utils"; 4 | 5 | export default Base.extend({ 6 | name: "close-panel", 7 | trigger: ".close-panel", 8 | 9 | init() { 10 | // Close panel support for dialog panels 11 | // Other modals are handled in pat-modal. 12 | const dialog_panel = this.el.closest("dialog"); 13 | if (dialog_panel) { 14 | events.add_event_listener( 15 | dialog_panel, 16 | "close-panel", 17 | "close-panel--dialog", 18 | () => { 19 | dialog_panel.close(); 20 | } 21 | ); 22 | } 23 | 24 | this.el.addEventListener("click", async (e) => { 25 | await utils.timeout(0); // Wait for other patterns, like pat-validation. 26 | 27 | if ( 28 | e.target.matches(":not([formnovalidate])") && 29 | e.target.matches("[type=submit], button:not([type=button])") && 30 | this.el.closest("form")?.checkValidity() === false 31 | ) { 32 | // Prevent closing an invalid form when submitting. 33 | return; 34 | } 35 | 36 | this.el.dispatchEvent( 37 | new Event("close-panel", { bubbles: true, cancelable: true }) 38 | ); 39 | }); 40 | }, 41 | }); 42 | -------------------------------------------------------------------------------- /src/pat/close-panel/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Closes a previously opened panels when clicking on elements with a ``close-panel`` class on it. 4 | 5 | The element with the ``close-panel`` class must be a child element of the panel which should be closed. 6 | 7 | This pattern works together with: 8 | 9 | - panels which are ```` elements 10 | - ``pat-modal`` panels, 11 | - ``pat-tooltip`` panels, 12 | - ``pat-notification`` panels. 13 | -------------------------------------------------------------------------------- /src/pat/close-panel/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pat-close-panel demo 5 | 6 | 7 | 8 | 13 | 14 | 15 | 16 | Example 17 | 18 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/pat/collapsible/_collapsible.scss: -------------------------------------------------------------------------------- 1 | @use "../../../_sass/settings"; 2 | @use "../../../_sass/components/button"; 3 | 4 | .pat-collapsible { 5 | margin-bottom: 0.5em; 6 | 7 | > *:first-child:before { 8 | content: "▼"; 9 | width: 1.5em; 10 | display: inline-block; 11 | } 12 | 13 | &.closed > *:first-child:before { 14 | content: "▶"; 15 | } 16 | 17 | > .panel-content { 18 | padding-top: 1em; 19 | padding-bottom: 1em; 20 | width: 100% !important; 21 | } 22 | 23 | > *:first-child { 24 | font-weight: normal; 25 | width: 100%; 26 | 27 | -moz-box-sizing: border-box; 28 | -webkit-box-sizing: border-box; 29 | box-sizing: border-box; 30 | // font-size: 0.8em; 31 | @include button.pat-button(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/pat/collapsible/collapsible-sources.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |

6 | Sed ut perspiciatis unde omnis iste natus error sit voluptatem 7 | accusantium doloremque laudantium, totam rem aperiam, eaque ipsa 8 | quae ab illo inventore veritatis et quasi architecto beatae 9 | vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia 10 | voluptas sit aspernatur aut odit aut fugit, sed quia 11 | consequuntur magni dolores eos qui ratione voluptatem sequi 12 | nesciunt. 13 |

14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /src/pat/colour-picker/_colour-picker.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | @use "spectrum-colorpicker/spectrum"; 3 | 4 | .checkNative, 5 | .checkPattern { 6 | font-size: 3vh; 7 | } 8 | 9 | #native { 10 | width: 5%; 11 | height: 4vh; 12 | } 13 | -------------------------------------------------------------------------------- /src/pat/colour-picker/colour-picker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Patterns pat-polyfill-colour - Polyfill for colour inputs. 3 | * 4 | * Copyright 2014 Marko Durkovic 5 | * Copyright 2014 Simplon B.V. - Wichert Akkerman 6 | */ 7 | import registry from "../../core/registry"; 8 | 9 | var _ = { 10 | name: "polyfill-color", 11 | trigger: "input.pat-colour-picker,input.pat-color-picker", 12 | async init($el) { 13 | await import("spectrum-colorpicker"); 14 | if (window.__patternslib_import_styles) { 15 | import("./_colour-picker.scss"); 16 | } 17 | return $el.spectrum({ preferredFormat: "hex" }); 18 | }, 19 | }; 20 | 21 | registry.register(_); 22 | export default _; 23 | -------------------------------------------------------------------------------- /src/pat/colour-picker/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | A pattern for creating a custom colour picker or polyfill. 4 | 5 | ## Documentation 6 | 7 | This pattern provides a styleable colour picker. It can be used as a fallback 8 | for browsers which don't yet support the HTML5 colour input. 9 | 10 | ### Examples 11 | 12 | ####Falling back to the browser's HTML5 picker if available. 13 | 14 | 15 | 16 | ####Enforcing the styled non-HTML5 picker universally. 17 | 18 | By default this pattern will NOT defer to the browser's HTML5 picker. 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/pat/colour-picker/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pat-colour-picker demo page 5 | 6 | 7 | 8 | 9 | 10 |
11 | 15 |
16 | 17 |

18 | The colour you have selected is : 19 | No colour selected 20 |

21 | 22 |
23 | 27 |
28 | 29 |

30 | The colour you have selected is : 31 | No colour selected 32 |

33 | 34 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/pat/date-picker/_date-picker.scss: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | @use "pikaday/scss/pikaday.scss"; 3 | -------------------------------------------------------------------------------- /src/pat/date-picker/i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "previousMonth": "Letzer Monat", 3 | "nextMonth": "Nächster Monat", 4 | "months": [ 5 | "Januar", 6 | "Februar", 7 | "März", 8 | "April", 9 | "Mai", 10 | "Juni", 11 | "Juli", 12 | "August", 13 | "September", 14 | "Oktober", 15 | "November", 16 | "Dezember" 17 | ], 18 | "weekdays": [ 19 | "Sonntag", 20 | "Montag", 21 | "Dienstag", 22 | "Mittwoch", 23 | "Donnerstag", 24 | "Freitag", 25 | "Samstag" 26 | ], 27 | "weekdaysShort": ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"] 28 | } 29 | -------------------------------------------------------------------------------- /src/pat/datetime-picker/_datetime-picker.scss: -------------------------------------------------------------------------------- 1 | .pat-datetime-picker__wrapper { 2 | input[type="date"], 3 | input[type="time"] { 4 | position: relative; 5 | display: inline-block; 6 | margin-right: 0.5em; 7 | } 8 | input[type="date"] { 9 | width: auto; 10 | } 11 | input[type="time"] { 12 | width: 10em; 13 | } 14 | button._now { 15 | margin-right: 0.2em; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/pat/datetime-picker/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | A pattern for creating a custom date picker or polyfill. 4 | 5 | ## Documentation 6 | 7 | This pattern provides a styleable date picker. It can be used as a fallback 8 | for browsers which don't yet support the HTML5 date input. 9 | 10 | ### Examples 11 | 12 | #### Enforcing the styled non-HTML5 picker universally. 13 | 14 | By default this pattern will NOT defer to the browser's HTML5 picker. 15 | 16 | 17 | 18 | #### Default value 19 | 20 | 21 | 22 | #### Specifying the "min" and "max" attributes. 23 | 24 | 25 | 26 | #### Show the week number. 27 | 28 | 29 | 30 | #### Multilingual support with German translations 31 | 32 | The picker's UI can be translated by providing a URL to the `i18n` option. This 33 | URL must point to a JSON encoded resource containing the translations. 34 | 35 | 36 | 37 | Here are all the i18n values in JSON format: 38 | 39 | { 40 | "previousMonth": "Previous Month", 41 | "nextMonth": "Next Month", 42 | "months": ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], 43 | "weekdays": ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], 44 | "weekdaysShort": ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"] 45 | } 46 | 47 | 48 | ### Option reference 49 | 50 | The HTML5 attributes `min` and `max` will be honoured. 51 | 52 | In addition, the following options can be passed to `data-pat-date-picker`: 53 | 54 | | Property | Type | Default Value | Available values | Description | 55 | | --------------------------- | ------- | ------------- | ---------------- | ------------------------------------------------------------ | 56 | | **week-numbers** | string | hide | show, hide | "show" will show the weeks' numbers in a leftmost column. | 57 | | **i18n** | URL | | | Provide a URL to a JSON resource which gives the i18n values. | 58 | | **first-day** | Integer | 0 | | Set the first day of the week (0 -> Sunday, 1-> Monday, ...). | 59 | -------------------------------------------------------------------------------- /src/pat/datetime-picker/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | pat-datetime-picker demo page 5 | 6 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
23 |
32 |
40 |
41 |
42 | 43 | 44 | -------------------------------------------------------------------------------- /src/pat/display-time/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | A pattern that makes dates easier to read. 4 | 5 | ## Documentation 6 | 7 | Example: 8 | 9 | 14 | 15 | 16 | ### Options reference 17 | 18 | | Property | Default value | Description | Type | 19 | | ----------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | 20 | | `output-format` | | For non-relative dates (the default, `from-now` set to `false`) show the date in the given format. For formatting options see: https://momentjs.com/docs/#/displaying/format/ | String | 21 | | `from-now` | `false` | Change the date to a relative date, relative from now. | Boolean | 22 | | `no-suffix` | `false` | For relative dates and no-suffix is set to `true`, do not show the suffix like `8 years` instead of `8 years ago`. | Boolean | 23 | | `format` | | Input parsing format. If not given (the default) the format is set automatically, if possible. For more information, see: https://momentjs.com/docs/#/parsing/string-format/ | String | 24 | | `locale` | | The locale to translate the resulting date/time string into. If not given (the default) the locale is retrieved from a `lang` attribute up in the DOM tree or `en`. | String | 25 | | `strict` | `false` | Strict parsing for the input format. See: https://momentjs.com/guides/#/parsing/strict-mode/ | Boolean | 26 | 27 | -------------------------------------------------------------------------------- /src/pat/equaliser/_equaliser.scss: -------------------------------------------------------------------------------- 1 | @use "../collapsible/collapsible"; 2 | 3 | .column > .panel, 4 | .columns > .panel { 5 | height: 100%; 6 | } 7 | -------------------------------------------------------------------------------- /src/pat/equaliser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Patterns — Equaliser 5 | 6 | 7 | 8 | 9 | 10 |
14 |
15 |
16 |
17 |

18 | Sed ut perspiciatis unde omnis iste natus error sit 19 | voluptatem accusantium doloremque laudantium, totam 20 | rem aperiam, eaque ipsa quae ab illo inventore 21 | veritatis et quasi architecto beatae vitae dicta 22 | sunt explicabo. Nemo enim ipsam voluptatem quia 23 | voluptas sit aspernatur aut odit aut fugit, sed quia 24 | consequuntur magni dolores eos qui ratione 25 | voluptatem sequi nesciunt. Neque porro quisquam est, 26 | qui dolorem ipsum quia dolor sit amet, consectetur, 27 | adipisci velit, sed quia non numquam. 28 |

29 |
30 |

More…

31 |

32 | Totam rem aperiam, eaque ipsa quae ab illo 33 | inventore veritatis et quasi architecto beatae 34 | vitae dicta sunt explicabo. 35 |

36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |

Minimal content

44 |
45 |
46 |
47 |
48 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/pat/expandable-tree/_expandable-tree.scss: -------------------------------------------------------------------------------- 1 | .pat-expandable { 2 | background-color: #f9f9f9; 3 | list-style-type: none; 4 | padding: 10px; 5 | margin-left: 0; 6 | 7 | .current { 8 | font-weight: bold; 9 | display: inline-block; 10 | color: red; 11 | } 12 | 13 | li { 14 | li { 15 | display: block; 16 | padding-left: 30px; 17 | } 18 | span.toggle { 19 | width: 1.2em; 20 | height: 1.2em; 21 | float: left; 22 | font-size: 1em; 23 | line-height: 1.2em; 24 | } 25 | 26 | ul { 27 | margin-bottom: 0; 28 | margin-left: 0; 29 | margin-top: 0; 30 | padding: 0; 31 | display: none; 32 | } 33 | &.open > ul, 34 | a { 35 | display: block; 36 | } 37 | } 38 | 39 | span.toggle:before { 40 | content: "▶"; 41 | } 42 | 43 | .open > span.toggle:before { 44 | content: "▼"; 45 | display: inline-block; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/pat/expandable-tree/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | Expandable trees are typically used in applications that need to outputs 4 | large amounts of hierarchically organised data. 5 | 6 | ## Documentation 7 | 8 | Expandable tree has nog configurable options. -------------------------------------------------------------------------------- /src/pat/expandable-tree/expandable-tree.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | import inject from "../inject/inject"; 3 | import Parser from "../../core/parser"; 4 | import registry from "../../core/registry"; 5 | 6 | export const parser = new Parser("expandable"); 7 | parser.addArgument("load-content"); 8 | 9 | var _ = { 10 | name: "expandable", 11 | trigger: "ul.pat-expandable", 12 | jquery_plugin: true, 13 | init: function ($el) { 14 | // make sure inject folders have a ul 15 | $el.find(".folder[data-pat-expandable]:not(:has(ul))").append("
    "); 16 | 17 | // find all folders that contain a ul 18 | var $folders = $el.find("li.folder:has(ul)"); 19 | 20 | // inject span.toggle as first child of each folder 21 | $folders.prepend(""); 22 | 23 | // all folders are implicitly closed 24 | $folders.filter(":not(.open,.closed)").addClass("closed"); 25 | 26 | // trigger open event for open folders 27 | $folders.filter(".open").trigger("patterns-folder-open"); 28 | 29 | // wire spans as control elements 30 | var $ctrls = $el.find("span.toggle"); 31 | $ctrls.each(function () { 32 | var $ctrl = $(this), 33 | $folder = $ctrl.parent(); 34 | $ctrl.on("click.pat-expandable", function () { 35 | $folder 36 | .toggleClass("open closed") 37 | .filter(".open[data-pat-expandable]") 38 | .patExpandable("loadContent"); 39 | }); 40 | }); 41 | return $el; 42 | }, 43 | loadContent: function ($el) { 44 | return $el.each(function () { 45 | var $el = $(this), 46 | url = parser.parse($el).loadContent, 47 | components = url.split("#"), 48 | base_url = components[0], 49 | id = components[1] ? "#" + components[1] : "body", 50 | opts = [ 51 | { 52 | url: base_url, 53 | source: id, 54 | $target: $el.find("ul"), 55 | dataType: "html", 56 | }, 57 | ]; 58 | inject.execute(opts, $el); 59 | }); 60 | }, 61 | }; 62 | registry.register(_); 63 | export default _; 64 | -------------------------------------------------------------------------------- /src/pat/expandable-tree/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Demo page 5 | 6 | 7 | 8 | 9 | 10 | 54 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/pat/focus/_focus.scss: -------------------------------------------------------------------------------- 1 | @use "../../../_sass/settings"; 2 | 3 | fieldset.focus > .legend, 4 | label.focus { 5 | color: settings.$colour-accent; 6 | } 7 | -------------------------------------------------------------------------------- /src/pat/focus/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | It is frequently useful to change the styling for labels or fieldsets if 4 | they contain an input element that has the focus. Patterns facilitate 5 | that by automatically adding a `focus` class. 6 | 7 | ## Documentation 8 | 9 | It is frequently useful to change the styling for labels or fieldsets if 10 | they contain an input element that has the focus. Patterns facilitate 11 | that by automatically adding a `focus` class. 12 | 13 | Let's look at a simple form: 14 | 15 |
    16 |
    17 | Generic info 18 | 19 | 20 |
    21 | 22 |
    23 | Details 24 | ... 25 |
    26 |
    27 | 28 | If the focus changes to the keywords input Patterns will add the `focus` 29 | class to the input element, its label and fieldset: 30 | 31 |
    32 |
    33 | Generic info 34 | 35 | 36 |
    37 | 38 |
    39 | Details 40 | ... 41 |
    42 |
    43 | 44 | It is not required to put the input element inside a label: labels will 45 | automatically be scanned for relevant `for` attributes. 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/pat/focus/focus.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @license 3 | * Patterns @VERSION@ focus - Manage focus class on fieldsets 4 | * 5 | * Copyright 2012 Simplon B.V. 6 | */ 7 | 8 | import $ from "jquery"; 9 | import registry from "../../core/registry"; 10 | import utils from "../../core/utils"; 11 | 12 | var focus = { 13 | name: "focus", 14 | 15 | onNewContent: function () { 16 | if ($(document.activeElement).is(":input")) 17 | focus._doFocus(document.activeElement); 18 | }, 19 | 20 | transform: function ($root) { 21 | $root.find(":input[placeholder]").each(function (ix, el) { 22 | var $relatives = utils.findRelatives(el); 23 | if (el.placeholder) $relatives.attr("data-placeholder", el.placeholder); 24 | }); 25 | $root.find(":input").each(focus.onChange); 26 | }, 27 | 28 | onFocus: function () { 29 | focus._doFocus(this); 30 | }, 31 | 32 | _updateHasValue: function (el) { 33 | var $relatives = utils.findRelatives(el); 34 | var hv = utils.hasValue(el); 35 | 36 | if (hv) { 37 | $relatives.addClass("has-value").attr("data-value", el.value); 38 | } else { 39 | $relatives 40 | .filter(function (ix, e) { 41 | const inputs = $(":input", e); 42 | for (var i = 0; i < inputs.length; i++) 43 | if (utils.hasValue(inputs[i])) return false; 44 | return true; 45 | }) 46 | .removeClass("has-value") 47 | .attr("data-value", null); 48 | } 49 | }, 50 | 51 | _doFocus: function (el) { 52 | var $relatives = utils.findRelatives(el); 53 | $relatives.addClass("focus"); 54 | this._updateHasValue($relatives); 55 | }, 56 | 57 | onBlur: function () { 58 | var $relatives = utils.findRelatives(this); 59 | 60 | $(document).one("mouseup keyup", function () { 61 | $relatives.filter(":not(:has(:input:focus))").removeClass("focus"); 62 | }); 63 | }, 64 | 65 | onChange: function () { 66 | focus._updateHasValue(this); 67 | }, 68 | }; 69 | 70 | $(document) 71 | .on("focus.patterns", ":input", focus.onFocus) 72 | .on("blur.patterns", ":input", focus.onBlur) 73 | .on("newContent", focus.onNewContent) 74 | .on("change.pat-focus keyup.pat-focus", ":input", focus.onChange) 75 | .on("input.pat-focus", ":input[type=range]", utils.debounce(focus.onChange, 50)); 76 | 77 | registry.register(focus); 78 | export default focus; 79 | -------------------------------------------------------------------------------- /src/pat/focus/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | focus pattern demo 5 | 6 | 7 | 8 | 9 | 10 |
    11 |

    Form one

    12 |
    13 | 16 | 23 |
    24 |
    25 | 26 |
    27 |

    Form two

    28 |
    29 | 30 | 31 |
    32 |
    33 | 34 | 35 | -------------------------------------------------------------------------------- /src/pat/forward/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | The _forward_ pattern forwards click events to another element(s). 4 | 5 | ## Documentation 6 | 7 | This pattern can be used to redirect a click on an element to one or more other elements. 8 | 9 | Submit form 10 |
    11 | Submit 12 |
    13 | 14 | If the trigger parameter is set to `auto`, the click event will be triggered 15 | immediately after the page is loaded. 16 | 17 | Autosubmit form 18 |
    19 | Submit 20 |
    21 | 22 | ### Option reference 23 | 24 | | Property | Description | Default | Allowed Values | Type | 25 | | ---------- | -------------------------------------------------------------------- | ------- | ---------------------- | ------------ | 26 | | `selector` | The element to which the click event should be forwarded. | | CSS Selector or `self` | CSS Selector | 27 | | `trigger` | When the forward action should be fired | `click` | `click | auto` | One of the mutually exclusive string values | 28 | | `delay` | Defines time in milliseconds for which the action should be deferred | null | integer | ms | 29 | 30 | Note: If the selector is `self` the handler gets unregistered after it has been run once. 31 | -------------------------------------------------------------------------------- /src/pat/forward/forward.js: -------------------------------------------------------------------------------- 1 | // Patterns forward - Forward click events 2 | import Base from "../../core/base"; 3 | import Parser from "../../core/parser"; 4 | import utils from "../../core/utils"; 5 | 6 | export const parser = new Parser("forward"); 7 | parser.addArgument("selector"); 8 | parser.addArgument("trigger", "click", ["click", "auto"]); 9 | parser.addArgument("delay"); 10 | 11 | export default Base.extend({ 12 | name: "forward", 13 | trigger: ".pat-forward", 14 | skip: false, 15 | 16 | init() { 17 | this.options = parser.parse(this.el, this.options); 18 | if (!this.options.selector) { 19 | return; 20 | } 21 | if (this.options.delay) { 22 | this.options.delay = utils.parseTime(this.options.delay); 23 | } 24 | 25 | this.el.addEventListener("click", this.on_click.bind(this)); 26 | if (this.options.trigger === "auto") { 27 | this.el.click(); 28 | } 29 | }, 30 | 31 | async on_click(event) { 32 | if (this.skip) { 33 | this.skip = false; 34 | return; 35 | } 36 | event.preventDefault(); 37 | if (this.options.delay) { 38 | await utils.timeout(this.options.delay); 39 | } 40 | let targets; 41 | if (this.options.selector === "self") { 42 | this.skip = true; 43 | targets = [this.el]; 44 | } else { 45 | targets = document.querySelectorAll(this.options.selector); 46 | } 47 | for (const el of targets) { 48 | el.click(); 49 | } 50 | }, 51 | }); 52 | 53 | // Notes: 54 | // 55 | // We're using `ELEMENT.click()` instead of 56 | // `ELEMENT.dispatchEvent(new Event("click"))`. 57 | // The latter doesn't get recognized by jQuery and does not invoke the default 58 | // action on an element. 59 | // 60 | -------------------------------------------------------------------------------- /src/pat/forward/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Toggle 5 | 6 | 7 | 8 | 9 | 10 |
    11 |
    12 |
    13 | 17 |
    18 |
    19 | 23 |
    24 |
    25 | 32 | 33 | 40 |
    41 |
    45 |
    46 |
    47 | 48 |
    49 | Click to reload in 2s 53 |
    54 | 55 | 56 | -------------------------------------------------------------------------------- /src/pat/fullscreen/_fullscreen.scss: -------------------------------------------------------------------------------- 1 | @use "../../../_sass/settings"; 2 | 3 | :fullscreen { 4 | background-color: transparent; 5 | } 6 | 7 | .pat-fullscreen { 8 | cursor: pointer; // show the pointer-cursor also on element, where it wouldn't 9 | } 10 | 11 | .pat-fullscreen-close-fullscreen { 12 | position: absolute; 13 | top: 1rem; 14 | right: 1rem; 15 | cursor: pointer; 16 | background: transparent; 17 | height: 3rem; 18 | width: 3rem; 19 | line-height: 3rem; 20 | margin: 0; 21 | padding: 0; 22 | text-indent: -1000px; 23 | overflow: hidden; 24 | border: none; 25 | 26 | &:before { 27 | content: "#{settings.$glyph-close}"; 28 | text-indent: 0; 29 | position: absolute; 30 | top: 0; 31 | right: 0; 32 | width: 3rem; 33 | font: normal 3rem fontello; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/pat/fullscreen/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | The _fullscreen_ pattern allows you to display any element in fullscreen-mode. 4 | 5 | ## Documentation 6 | 7 | When an element with the `pat-fullscreen` class is clicked another element is set to fullscreen. 8 | There is also a second pattern `pat-fullscreen-close` which is triggered on the `close-fullscreen` CSS class. 9 | It triggers a close fullscreen when clicking. 10 | This is done as a seperate pattern so that HTML structures injected with `pat-inject` are initialized and working correctly. 11 | 12 | The element sent to fullscreen is defined so: 13 | 14 | 1. If there is a `data-pat-fullscreen` with a selector option, that one is used. 15 | 2. if the pat-fullscreen element is an anchor link, it's href attribute is used to point to an element with the id specified in the href attribute. 16 | 3. Otherwise, the body is sent to fullscreen. 17 | 18 | You can add a close button by setting the `close-button` option to `show`. 19 | 20 | Anyways, any `.close-fullscreen` element within the fullscreen element itself will be used to close the fullscreen. 21 | 22 | See examples below. 23 | 24 | ### Examples 25 | 26 | Fullscreen via anchor-element: 27 | 28 |
    29 | Open in fullscreen 30 |
    31 | 32 | Configuration via data attributes: 33 | 34 |
    35 | 36 |
    37 | 38 | Custom close buttons: 39 | 40 |
    41 | 42 | 43 |
    44 | 45 | Open the `body` element in fullscreen without giving any options. 46 | 47 | 48 | 49 | ### Option reference 50 | 51 | The fullscreen pattern can be configured through a `data-pat-fullscreen` attribute. 52 | The available options are: 53 | 54 | | Field | Default | Options | Description | 55 | | -------------- | ------- | -------------- | -------------------------------------------------------------------------------------------------- | 56 | | `selector` | `null` | A CSS selector | The target element which should be shown in fullscreen. If not given, open the body in fullscreen. | 57 | | `close-button` | `none` | `none`, `show` | `show` if a exit button should be shown when entering fullscreen mode. | 58 | -------------------------------------------------------------------------------- /src/pat/fullscreen/fullscreen-close.js: -------------------------------------------------------------------------------- 1 | import Base from "../../core/base"; 2 | 3 | export default Base.extend({ 4 | name: "fullscreen-close", 5 | trigger: ".close-fullscreen", 6 | async init() { 7 | const Screenfull = (await import("screenfull")).default; 8 | 9 | this.$el[0].addEventListener("click", function () { 10 | // no prevent-default nor stop propagation to let 11 | // the button also do other stuff. 12 | Screenfull.exit(); 13 | }); 14 | }, 15 | }); 16 | -------------------------------------------------------------------------------- /src/pat/gallery/default-skin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/default-skin.png -------------------------------------------------------------------------------- /src/pat/gallery/default-skin.svg: -------------------------------------------------------------------------------- 1 | default-skin 2 -------------------------------------------------------------------------------- /src/pat/gallery/full-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/full-1.jpg -------------------------------------------------------------------------------- /src/pat/gallery/full-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/full-2.jpg -------------------------------------------------------------------------------- /src/pat/gallery/full-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/full-3.jpg -------------------------------------------------------------------------------- /src/pat/gallery/full-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/full-4.jpg -------------------------------------------------------------------------------- /src/pat/gallery/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/icons.png -------------------------------------------------------------------------------- /src/pat/gallery/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/icons@2x.png -------------------------------------------------------------------------------- /src/pat/gallery/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/loader.gif -------------------------------------------------------------------------------- /src/pat/gallery/preloader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/preloader.gif -------------------------------------------------------------------------------- /src/pat/gallery/thumb-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/thumb-1.jpg -------------------------------------------------------------------------------- /src/pat/gallery/thumb-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/thumb-2.jpg -------------------------------------------------------------------------------- /src/pat/gallery/thumb-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/gallery/thumb-3.jpg -------------------------------------------------------------------------------- /src/pat/grid/documentation.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | The grid patterns allows you create responsive layout, without having to write CSS for it. The Patterns Grid pattern is based on the [Zurb Foundation grid system](http://foundation.zurb.com/grid.php "The Zurb foundation website"). 4 | 5 | ## Documentation 6 | 7 | ### The grid 8 | 9 | **Create powerful multi-device layouts quickly and easily with the 12-column, nestable Foundation grid. If you're familiar with grid systems, you'll feel right at home.** 10 | 11 | #### The Basics 12 | 13 | The grid is built around two key elements: rows and columns. Rows create a max-width and contain the columns; columns create the actual structure. For layouts to work properly, always put your page content inside a row and a column. 14 | 15 | What you need to know is that **columns don't have a fixed width.** They can vary based on the resolution of the screen, or the size of the window (try scaling down this window to see what we mean). Design with that in mind. 16 | 17 | #### Nesting Support 18 | 19 | The grid allows for nesting down as far as you'd like, though at a certain point it will get absurd. You can use this nesting to create quite complex layouts, as well as some other tricks like form layouts or visual elements. 20 | 21 | #### Offsets 22 | 23 | Offsets allow you to create additional space between columns in a row. The offsets run from offset-by-one all the way up to offset-by-eleven. Like the rest of the grid, they're nestable. 24 | 25 | ![image](/code/src/pat/grid/offsets.png) 26 | 27 | #### Centered Columns 28 | 29 | Centred columns are placed in the middle of the row. This does not centre their content, but centres the grid element itself. This is a convenient way to make sure a block is centred, even if you change the number of columns it contains. Note: There cannot be any other column blocks in the row for this to work. 30 | 31 | #### Source Ordering 32 | 33 | Sometimes within the grid you want the order of your markup to not necessarily be the same as the order items are flowed into the grid. Using our source ordering classes, `.push-#/pull-#`, you can shift columns around on desktops and tablets. On phones, the grid will still be linearised into the order of the markup. 34 | 35 | ![image](/code/src/pat/grid/source-ordering.png) 36 | 37 | The syntax supports push and pull for two to ten columns, and is added directly to the columns themselves. 38 | 39 | --- 40 | 41 | The above text is based on the [Zurb Foundation grid documentation](http://foundation.zurb.com/docs/grid.php) 42 | -------------------------------------------------------------------------------- /src/pat/grid/grid.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/grid/grid.js -------------------------------------------------------------------------------- /src/pat/grid/offsets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/grid/offsets.png -------------------------------------------------------------------------------- /src/pat/grid/source-ordering.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/grid/source-ordering.png -------------------------------------------------------------------------------- /src/pat/image-crop/Jcrop.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/image-crop/Jcrop.gif -------------------------------------------------------------------------------- /src/pat/image-crop/pool.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/image-crop/pool.jpg -------------------------------------------------------------------------------- /src/pat/inject/_inject.scss: -------------------------------------------------------------------------------- 1 | .blue { 2 | background-color: blue; 3 | color: white; 4 | } 5 | 6 | .red { 7 | background-color: red; 8 | color: white; 9 | } 10 | 11 | form.pat-inject, 12 | fieldset.pat-inject { 13 | &.executing { 14 | [type="submit"] { 15 | -ms-pointer-events: none; 16 | -moz-pointer-events: none; 17 | -webkit-pointer-events: none; 18 | pointer-events: none; 19 | opacity: 0.5; 20 | } 21 | } 22 | } 23 | 24 | a.pat-inject { 25 | &.executing { 26 | -ms-pointer-events: none; 27 | -moz-pointer-events: none; 28 | -webkit-pointer-events: none; 29 | pointer-events: none; 30 | opacity: 0.5; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/pat/inject/_injection.scss: -------------------------------------------------------------------------------- 1 | /* @group Throbber */ 2 | 3 | .injecting * { 4 | opacity: 0.19; 5 | } 6 | 7 | .injecting:before { 8 | opacity: 1; 9 | position: absolute; 10 | top: 50%; 11 | left: 50%; 12 | content: "\e838"; 13 | width: 50px; 14 | height: 50px; 15 | margin-top: -25px; 16 | margin-left: -25px; 17 | z-index: 1000; 18 | font: 50px/50px fontello; 19 | text-shadow: white 0 0 2px; 20 | text-align: center; 21 | -moz-animation: spin 2s infinite linear; 22 | -o-animation: spin 2s infinite linear; 23 | -webkit-animation: spin 2s infinite linear; 24 | animation: spin 2s infinite linear; 25 | } 26 | 27 | /* @end */ 28 | -------------------------------------------------------------------------------- /src/pat/inject/demo/backend-action.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Backend Action Only 4 | 5 | 6 |
    7 | This is a backend action that will not be injected anywhere. 8 |
    9 | 10 | 11 | -------------------------------------------------------------------------------- /src/pat/inject/demo/cocteau.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/inject/demo/cocteau.jpg -------------------------------------------------------------------------------- /src/pat/inject/demo/history-inject-source.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Gilgamesh Epos 5 | 6 | 7 | 8 | 9 |
    10 |

    Tablet 1

    11 |

    12 | of him who knew the most of all men know;
    13 | who made the journey; heartbroken; reconciled;
    14 |
    15 | who knew the way things were before the Flood,
    16 | the secret things, the mystery; who went
    17 |
    18 | to the end of the earth, and over; who returned,
    19 | and wrote the story on a tablet of stone.
    20 |
    21 | He built Uruk. He built the keeping place
    22 | of Anu and Ishtar. The outer wall
    23 |
    24 | shines in the sun like brightest copper; the inner
    25 | wall is beyond the imagining of kings.
    26 |

    27 |

    28 | — Gilgamesh 29 |

    30 |
    31 | 32 | 33 | -------------------------------------------------------------------------------- /src/pat/inject/demo/history-page1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Injection history demo page 5 | 6 | 7 | 8 | 9 | 10 |

    Injection history demo page 1

    11 |
    12 |

    This is page1

    13 | 14 | 15 | 46 | Anchors also trigger onpopstate events 49 |
    50 | 51 | 52 | -------------------------------------------------------------------------------- /src/pat/inject/demo/history-page2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Injection history demo page 5 | 6 | 7 | 8 | 9 | 10 |

    Injection history demo page 2

    11 |
    12 |

    This is page2

    13 | 14 | 15 | 46 | Anchors also trigger onpopstate events 49 |
    50 | 51 | 52 | -------------------------------------------------------------------------------- /src/pat/inject/demo/history-page3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Injection history demo page 5 | 6 | 7 | 8 | 9 | 10 |

    Injection history demo page 3

    11 |
    12 |

    This is page3

    13 | 14 | 15 | 46 | Anchors also trigger onpopstate events 49 |
    50 | 51 | 52 | -------------------------------------------------------------------------------- /src/pat/inject/demo/history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Injection history demo page 5 | 6 | 7 | 8 | 9 | 10 |

    Back to the main inject demo.

    11 |

    This is the index

    12 | 13 | 44 | Anchors also trigger onpopstate events 47 |
    Content will appear here…
    48 | 49 | 50 | -------------------------------------------------------------------------------- /src/pat/inject/demo/inject-form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |

    Here is the text that shows if it worked…

    5 | 6 | 7 | -------------------------------------------------------------------------------- /src/pat/inject/demo/rilke.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/inject/demo/rilke.jpg -------------------------------------------------------------------------------- /src/pat/inject/demo/test_404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 404 5 | 6 | 7 | 8 | 9 |

    oh-nose!

    10 |

    11 | 12 | you reached the internet's dead end. 13 | 14 |

    15 |

    16 | you better watch some youtube videos. 17 |

    18 | 19 | 20 | -------------------------------------------------------------------------------- /src/pat/inject/demo/wilde.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Patternslib/Patterns/25bb1f7956c00043cadcad84b7ac48885f80a06f/src/pat/inject/demo/wilde.jpg -------------------------------------------------------------------------------- /src/pat/legend/legend.js: -------------------------------------------------------------------------------- 1 | import $ from "jquery"; 2 | import registry from "../../core/registry"; 3 | import utils from "../../core/utils"; 4 | import dom from "../../core/dom"; 5 | 6 | var legend = { 7 | name: "legend", 8 | trigger: "legend", 9 | 10 | _convertToIframes: function ($root) { 11 | $root.findInclusive("object[type='text/html']").each(function () { 12 | var $object = $(this), 13 | $iframe = $("