├── .gitignore
├── README.md
├── assets
├── images
│ └── favicon.png
├── js
│ ├── app.js
│ ├── components
│ │ └── component.js
│ └── modernizr.js
└── scss
│ ├── app.scss
│ ├── base.scss
│ ├── components
│ ├── alpinejs.scss
│ └── links.scss
│ └── utilities
│ ├── font-face.scss
│ ├── rem.scss
│ └── transition.scss
├── gulpfile.js
├── package-lock.json
├── package.json
├── tailwind.config.js
└── web
├── dist
├── css
│ └── app.css
├── images
│ └── favicon.png
└── js
│ └── app.js
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | # Gulp / Packages
2 |
3 | node_modules
4 |
5 | # Sass
6 |
7 | *.sassc
8 | .sass-cache/*
9 | .sass-cache
10 | *.css.map
11 |
12 | # Javascript
13 |
14 | *.js.map
15 |
16 | # OS Files
17 |
18 | .DS_Store
19 | *.DS_Store
20 | .DS_Store?
21 | ._*
22 | .Spotlight-V100
23 | .Trashes
24 | ehthumbs.db
25 | Thumbs.db
26 |
27 | # Craft CMS
28 |
29 | cpresources
30 | vendor
31 | .env
32 | *.log
33 | storage/*
34 | config/license.key
35 |
36 | # Asset Source Folders
37 |
38 | web/uploads
39 | public/uploads
40 | public_html/uploads
41 |
42 | # Log files
43 |
44 | npm-debug.log*
45 | yarn-debug.log*
46 | yarn-error.log*
47 |
48 | # Editor directories and files
49 |
50 | .idea
51 | .vscode
52 | *.suo
53 | *.ntvs*
54 | *.njsproj
55 | *.sln
56 | *.sw*
57 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tailwind CSS
2 |
3 | This is a boilerplate [MadeByShape](https://madebyshape.co.uk) use internally for projects.
4 |
5 | It utilises the [Tailwind CSS] (https://tailwindcss.com) framework, to enable rapid development using utility / helper classes, with a mixture of BEM.
6 |
7 | ## Contents
8 |
9 | - [Installing](#installing)
10 | - [Compiling](#compiling)
11 | - [JS/CSS Dependencies](#js-css-dependencies)
12 | - [Framework](#framework)
13 | - [Framework Plugins](#framework-plugins)
14 | - [Colours](#colours)
15 | - [CSS Blocks](#css-blocks)
16 | - [CSS Helpers](#css-helpers)
17 | - [CSS Utilities](#css-utilities)
18 | - [JS Components](#js-components)
19 | - [JS Naming](#js-naming)
20 | - [Favicons](#favicons)
21 |
22 | ### Installing
23 |
24 | @TODO
25 |
26 | ### Compiling
27 |
28 | Use Gulp to run tasks within the project. See the `gulpfile.js` file for a list of available individual tasks. The build tasks are:
29 |
30 | - `gulp dev`
31 | - `gulp production`
32 |
33 | All Gulp settings are stored in the `package.json` file, e.g. If you need to change the public folder from `web/` then edit `paths > public` in this file.
34 |
35 | All assets should be placed in the root folder `assets`, seperated in to subfolders (E.g. `scss`, `js` etc). Use the `web/dist` folder to store any public files.
36 |
37 | Any files placed inside `assets` will be compiled, minified and optimised and then moved to the `dist` folder.
38 |
39 | NOTE: Never place files directly into the `web/dist` folder, as these can be overwritten sometimes via build commands.
40 |
41 | ### JS/CSS Dependencies
42 |
43 | Install all plugins and library dependencies using `npm`. Use the `cssDependencies` and `jsDependencies` arrays in `package.json` to add dependency files straight from the `node_modules` folder.
44 |
45 | For example, if the JS file required for the project is located in `path/to/the/node_modules/jquery/dist/jquery.js` add this path to the `jsDependencies` array without the `node_modules` folder (`jquery/dist/jquery.js`) and compile.
46 |
47 | ### Framework
48 |
49 | [Tailwind CSS] (https://tailwindcss.com) is used as the core framework - Read the docs to use this framework https://tailwindcss.com/docs
50 |
51 | Edit the `tailwind.config.js` whenever you need to modify / add new CSS utility classes.
52 |
53 | Use the `@apply` in custom CSS components where possible.
54 |
55 | For a grid, use Flex box mixed with width utilities as specified in the Tailwind CSS docs (https://tailwindcss.com/components/grids)
56 |
57 | ### Framework Plugins
58 |
59 | - Aspect Ratio (https://github.com/webdna/tailwindcss-aspect-ratio)
60 | - Transitions (https://github.com/benface/tailwindcss-transitions)
61 | - Transforms (https://github.com/benface/tailwindcss-transforms)
62 |
63 | ### Colours
64 |
65 | Although we're English, use the word `color` where possible (Over `colour`).
66 |
67 | All brand colours are specified using `primary`, `secondary` etc hierarchy. `500` is the base colour, with numbers lower (E.g. `300`) being lighter colours, and numbers (E.g. `800`) higher being darker colours.
68 |
69 | ### CSS Blocks
70 |
71 | Use BEM (http://getbem.com) style of naming when creating bespoke blocks But try to use `@apply` where possible to use existing CSS rules generated by Tailwind.
72 |
73 | Example:
74 |
75 | ```
76 | .card
77 | .card__content
78 | .card__content--large
79 | ```
80 |
81 | ### CSS Components
82 |
83 | CSS Components are styles that are used for repeat elements throughout a project. They are created in a separate component file in `assets/scss/components`. Try to avoid creating components where possible and use utility classes.
84 |
85 | Name | Base Class | File | Description
86 | --- | --- | --- | ---
87 | Button | `.button` | `button.scss` | Applies bases styles for buttons such as hovers and transition.
88 | Form | `.form` | `form.scss` | Applies base styles for form elements (Fields, Labels etc)
89 | Heading | `.heading` | `headings.scss` | Used to apply base styles to headings (Especially used with `.rich-text`).
90 | Link | `.link` | `links.scss` | Used to apply base styles to links.
91 | Rich Text | `.rich-text` | `rich-text.scss` | Applies base styles to tags used inside redactor (Rich text) fields.
92 | Section | `.section` | `section.scss` | Used to limit the max width of a site, and adds a site gutter.
93 | Transition | `.transition` | `transitions.scss` | Applies transitions classes to be used on links etc.
94 |
95 |
96 | ### CSS Helpers
97 |
98 | CSS Helpers are usually SCSS mixins or functions that can be used within components or blocks. They are created in separate helper files in `assets/scss/helpers`. If a new helper is created, or a helper is modified for a project consider submitting as a pull request to be used in future projects.
99 |
100 | Name | Property | File | Description
101 | --- | --- | --- | ---
102 | Font Face | `font-face($family, $filename, $weight, $style)` | `font-face.scss` | Allows use of custom fonts within CSS. Ideally place this within `base.scss` when being used.
103 | Hover | `hover()` | `hover.scss` | Used to detect if a browser supports `:hover`
104 | REM | `rem($size)` | `rem.scss` | Converts pixels (px) to REM values
105 |
106 | ### JS Components
107 |
108 | JS Components are chunks of functionality that do a specific function. E.g. You could have a component for creating a slideshow which includes when the slideshow loads, when it's resized etc. They are created in a separate a component file in `assets/js/components` using the following syntax:
109 |
110 | ```
111 | var component = {
112 | var: {
113 | object: '.js-component'
114 | },
115 | scroll: function(){},
116 | resize: function(){},
117 | load: function(){}
118 | }
119 | ```
120 |
121 | When a component is required to be run add this to the `assets/js/app.js` file in the appropriate method (`load`, `resize`, `scroll`) by calling the correct method on the component e.g. `component.load();` or `component.resize()`.
122 |
123 | ### JS Naming
124 |
125 | Try to avoid linking any JS to any CSS classes or utilities to avoid any conflict.
126 |
127 | Name your JS classes the same as your components in kebab case and prefix your component classes with `.js-` so developers know this relates to a specific JS function.
128 |
129 | ### Favicons
130 |
131 | Place a file named `favicon.png` in `assets/images` to generate a favicon. Running `gulp favicon` will generate this and put the appropriate files in the `dist/images` folder. Use `gulp images` to optimise these files.
132 |
133 | ## Roadmap
134 |
--------------------------------------------------------------------------------
/assets/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madebyshape/tailwind-css/c131d2bc030d70b88e2f8d71bd150634eb82407b/assets/images/favicon.png
--------------------------------------------------------------------------------
/assets/js/app.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | hidden: 'is-hidden',
3 | visible: 'is-visible',
4 | selected: 'is-selected',
5 | active: 'is-active',
6 | loading: 'is-loading'
7 | }
8 |
9 | window.addEventListener(
10 | 'load',
11 | function() {
12 | // e.g. component.init();
13 | }
14 | );
15 |
16 | window.addEventListener(
17 | 'resize',
18 | function() {
19 | // e.g. component.resize();
20 | }
21 | );
22 |
23 | window.addEventListener(
24 | 'scroll',
25 | function() {
26 | // e.g. component.scroll();
27 | }
28 | );
--------------------------------------------------------------------------------
/assets/js/components/component.js:
--------------------------------------------------------------------------------
1 | var component = {
2 | var: {
3 | object: '.js-component'
4 | },
5 | scroll: function(){},
6 | resize: function(){},
7 | init: function(){}
8 | }
9 |
--------------------------------------------------------------------------------
/assets/js/modernizr.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * modernizr v3.11.0
3 | * Build https://modernizr.com/download?-supports-addtest-printshiv-setclasses-testprop-dontmin
4 | *
5 | * Copyright (c)
6 | * Faruk Ates
7 | * Paul Irish
8 | * Alex Sexton
9 | * Ryan Seddon
10 | * Patrick Kettner
11 | * Stu Cox
12 | * Richard Herrera
13 | * Veeck
14 |
15 | * MIT License
16 | */
17 |
18 | /*
19 | * Modernizr tests which native CSS3 and HTML5 features are available in the
20 | * current UA and makes the results available to you in two ways: as properties on
21 | * a global `Modernizr` object, and as classes on the `` element. This
22 | * information allows you to progressively enhance your pages with a granular level
23 | * of control over the experience.
24 | */
25 |
26 | ;(function(scriptGlobalObject, window, document, undefined){
27 |
28 | var tests = [];
29 |
30 |
31 | /**
32 | * ModernizrProto is the constructor for Modernizr
33 | *
34 | * @class
35 | * @access public
36 | */
37 | var ModernizrProto = {
38 | // The current version, dummy
39 | _version: '3.11.0',
40 |
41 | // Any settings that don't work as separate modules
42 | // can go in here as configuration.
43 | _config: {
44 | 'classPrefix': '',
45 | 'enableClasses': true,
46 | 'enableJSClass': true,
47 | 'usePrefixes': true
48 | },
49 |
50 | // Queue of tests
51 | _q: [],
52 |
53 | // Stub these for people who are listening
54 | on: function(test, cb) {
55 | // I don't really think people should do this, but we can
56 | // safe guard it a bit.
57 | // -- NOTE:: this gets WAY overridden in src/addTest for actual async tests.
58 | // This is in case people listen to synchronous tests. I would leave it out,
59 | // but the code to *disallow* sync tests in the real version of this
60 | // function is actually larger than this.
61 | var self = this;
62 | setTimeout(function() {
63 | cb(self[test]);
64 | }, 0);
65 | },
66 |
67 | addTest: function(name, fn, options) {
68 | tests.push({name: name, fn: fn, options: options});
69 | },
70 |
71 | addAsyncTest: function(fn) {
72 | tests.push({name: null, fn: fn});
73 | }
74 | };
75 |
76 |
77 |
78 | // Fake some of Object.create so we can force non test results to be non "own" properties.
79 | var Modernizr = function() {};
80 | Modernizr.prototype = ModernizrProto;
81 |
82 | // Leak modernizr globally when you `require` it rather than force it here.
83 | // Overwrite name so constructor name is nicer :D
84 | Modernizr = new Modernizr();
85 |
86 |
87 |
88 | var classes = [];
89 |
90 |
91 | /**
92 | * is returns a boolean if the typeof an obj is exactly type.
93 | *
94 | * @access private
95 | * @function is
96 | * @param {*} obj - A thing we want to check the type of
97 | * @param {string} type - A string to compare the typeof against
98 | * @returns {boolean} true if the typeof the first parameter is exactly the specified type, false otherwise
99 | */
100 | function is(obj, type) {
101 | return typeof obj === type;
102 | }
103 |
104 | ;
105 |
106 | /**
107 | * Run through all tests and detect their support in the current UA.
108 | *
109 | * @access private
110 | * @returns {void}
111 | */
112 | function testRunner() {
113 | var featureNames;
114 | var feature;
115 | var aliasIdx;
116 | var result;
117 | var nameIdx;
118 | var featureName;
119 | var featureNameSplit;
120 |
121 | for (var featureIdx in tests) {
122 | if (tests.hasOwnProperty(featureIdx)) {
123 | featureNames = [];
124 | feature = tests[featureIdx];
125 | // run the test, throw the return value into the Modernizr,
126 | // then based on that boolean, define an appropriate className
127 | // and push it into an array of classes we'll join later.
128 | //
129 | // If there is no name, it's an 'async' test that is run,
130 | // but not directly added to the object. That should
131 | // be done with a post-run addTest call.
132 | if (feature.name) {
133 | featureNames.push(feature.name.toLowerCase());
134 |
135 | if (feature.options && feature.options.aliases && feature.options.aliases.length) {
136 | // Add all the aliases into the names list
137 | for (aliasIdx = 0; aliasIdx < feature.options.aliases.length; aliasIdx++) {
138 | featureNames.push(feature.options.aliases[aliasIdx].toLowerCase());
139 | }
140 | }
141 | }
142 |
143 | // Run the test, or use the raw value if it's not a function
144 | result = is(feature.fn, 'function') ? feature.fn() : feature.fn;
145 |
146 | // Set each of the names on the Modernizr object
147 | for (nameIdx = 0; nameIdx < featureNames.length; nameIdx++) {
148 | featureName = featureNames[nameIdx];
149 | // Support dot properties as sub tests. We don't do checking to make sure
150 | // that the implied parent tests have been added. You must call them in
151 | // order (either in the test, or make the parent test a dependency).
152 | //
153 | // Cap it to TWO to make the logic simple and because who needs that kind of subtesting
154 | // hashtag famous last words
155 | featureNameSplit = featureName.split('.');
156 |
157 | if (featureNameSplit.length === 1) {
158 | Modernizr[featureNameSplit[0]] = result;
159 | } else {
160 | // cast to a Boolean, if not one already or if it doesnt exist yet (like inputtypes)
161 | if (!Modernizr[featureNameSplit[0]] || Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
162 | Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
163 | }
164 |
165 | Modernizr[featureNameSplit[0]][featureNameSplit[1]] = result;
166 | }
167 |
168 | classes.push((result ? '' : 'no-') + featureNameSplit.join('-'));
169 | }
170 | }
171 | }
172 | }
173 | ;
174 |
175 | /**
176 | * docElement is a convenience wrapper to grab the root element of the document
177 | *
178 | * @access private
179 | * @returns {HTMLElement|SVGElement} The root element of the document
180 | */
181 | var docElement = document.documentElement;
182 |
183 |
184 | /**
185 | * A convenience helper to check if the document we are running in is an SVG document
186 | *
187 | * @access private
188 | * @returns {boolean}
189 | */
190 | var isSVG = docElement.nodeName.toLowerCase() === 'svg';
191 |
192 |
193 |
194 | /**
195 | * setClasses takes an array of class names and adds them to the root element
196 | *
197 | * @access private
198 | * @function setClasses
199 | * @param {string[]} classes - Array of class names
200 | */
201 | // Pass in an and array of class names, e.g.:
202 | // ['no-webp', 'borderradius', ...]
203 | function setClasses(classes) {
204 | var className = docElement.className;
205 | var classPrefix = Modernizr._config.classPrefix || '';
206 |
207 | if (isSVG) {
208 | className = className.baseVal;
209 | }
210 |
211 | // Change `no-js` to `js` (independently of the `enableClasses` option)
212 | // Handle classPrefix on this too
213 | if (Modernizr._config.enableJSClass) {
214 | var reJS = new RegExp('(^|\\s)' + classPrefix + 'no-js(\\s|$)');
215 | className = className.replace(reJS, '$1' + classPrefix + 'js$2');
216 | }
217 |
218 | if (Modernizr._config.enableClasses) {
219 | // Add the new classes
220 | if (classes.length > 0) {
221 | className += ' ' + classPrefix + classes.join(' ' + classPrefix);
222 | }
223 | if (isSVG) {
224 | docElement.className.baseVal = className;
225 | } else {
226 | docElement.className = className;
227 | }
228 | }
229 | }
230 |
231 | ;
232 |
233 | /**
234 | * hasOwnProp is a shim for hasOwnProperty that is needed for Safari 2.0 support
235 | *
236 | * @author kangax
237 | * @access private
238 | * @function hasOwnProp
239 | * @param {object} object - The object to check for a property
240 | * @param {string} property - The property to check for
241 | * @returns {boolean}
242 | */
243 |
244 | // hasOwnProperty shim by kangax needed for Safari 2.0 support
245 | var hasOwnProp;
246 |
247 | (function() {
248 | var _hasOwnProperty = ({}).hasOwnProperty;
249 | /* istanbul ignore else */
250 | /* we have no way of testing IE 5.5 or safari 2,
251 | * so just assume the else gets hit */
252 | if (!is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined')) {
253 | hasOwnProp = function(object, property) {
254 | return _hasOwnProperty.call(object, property);
255 | };
256 | }
257 | else {
258 | hasOwnProp = function(object, property) { /* yes, this can give false positives/negatives, but most of the time we don't care about those */
259 | return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
260 | };
261 | }
262 | })();
263 |
264 |
265 |
266 |
267 | // _l tracks listeners for async tests, as well as tests that execute after the initial run
268 | ModernizrProto._l = {};
269 |
270 | /**
271 | * Modernizr.on is a way to listen for the completion of async tests. Being
272 | * asynchronous, they may not finish before your scripts run. As a result you
273 | * will get a possibly false negative `undefined` value.
274 | *
275 | * @memberOf Modernizr
276 | * @name Modernizr.on
277 | * @access public
278 | * @function on
279 | * @param {string} feature - String name of the feature detect
280 | * @param {Function} cb - Callback function returning a Boolean - true if feature is supported, false if not
281 | * @returns {void}
282 | * @example
283 | *
284 | * ```js
285 | * Modernizr.on('flash', function( result ) {
286 | * if (result) {
287 | * // the browser has flash
288 | * } else {
289 | * // the browser does not have flash
290 | * }
291 | * });
292 | * ```
293 | */
294 | ModernizrProto.on = function(feature, cb) {
295 | // Create the list of listeners if it doesn't exist
296 | if (!this._l[feature]) {
297 | this._l[feature] = [];
298 | }
299 |
300 | // Push this test on to the listener list
301 | this._l[feature].push(cb);
302 |
303 | // If it's already been resolved, trigger it on next tick
304 | if (Modernizr.hasOwnProperty(feature)) {
305 | // Next Tick
306 | setTimeout(function() {
307 | Modernizr._trigger(feature, Modernizr[feature]);
308 | }, 0);
309 | }
310 | };
311 |
312 | /**
313 | * _trigger is the private function used to signal test completion and run any
314 | * callbacks registered through [Modernizr.on](#modernizr-on)
315 | *
316 | * @memberOf Modernizr
317 | * @name Modernizr._trigger
318 | * @access private
319 | * @function _trigger
320 | * @param {string} feature - string name of the feature detect
321 | * @param {Function|boolean} [res] - A feature detection function, or the boolean =
322 | * result of a feature detection function
323 | * @returns {void}
324 | */
325 | ModernizrProto._trigger = function(feature, res) {
326 | if (!this._l[feature]) {
327 | return;
328 | }
329 |
330 | var cbs = this._l[feature];
331 |
332 | // Force async
333 | setTimeout(function() {
334 | var i, cb;
335 | for (i = 0; i < cbs.length; i++) {
336 | cb = cbs[i];
337 | cb(res);
338 | }
339 | }, 0);
340 |
341 | // Don't trigger these again
342 | delete this._l[feature];
343 | };
344 |
345 | /**
346 | * addTest allows you to define your own feature detects that are not currently
347 | * included in Modernizr (under the covers it's the exact same code Modernizr
348 | * uses for its own [feature detections](https://github.com/Modernizr/Modernizr/tree/master/feature-detects)).
349 | * Just like the official detects, the result
350 | * will be added onto the Modernizr object, as well as an appropriate className set on
351 | * the html element when configured to do so
352 | *
353 | * @memberOf Modernizr
354 | * @name Modernizr.addTest
355 | * @optionName Modernizr.addTest()
356 | * @optionProp addTest
357 | * @access public
358 | * @function addTest
359 | * @param {string|object} feature - The string name of the feature detect, or an
360 | * object of feature detect names and test
361 | * @param {Function|boolean} test - Function returning true if feature is supported,
362 | * false if not. Otherwise a boolean representing the results of a feature detection
363 | * @returns {object} the Modernizr object to allow chaining
364 | * @example
365 | *
366 | * The most common way of creating your own feature detects is by calling
367 | * `Modernizr.addTest` with a string (preferably just lowercase, without any
368 | * punctuation), and a function you want executed that will return a boolean result
369 | *
370 | * ```js
371 | * Modernizr.addTest('itsTuesday', function() {
372 | * var d = new Date();
373 | * return d.getDay() === 2;
374 | * });
375 | * ```
376 | *
377 | * When the above is run, it will set Modernizr.itstuesday to `true` when it is tuesday,
378 | * and to `false` every other day of the week. One thing to notice is that the names of
379 | * feature detect functions are always lowercased when added to the Modernizr object. That
380 | * means that `Modernizr.itsTuesday` will not exist, but `Modernizr.itstuesday` will.
381 | *
382 | *
383 | * Since we only look at the returned value from any feature detection function,
384 | * you do not need to actually use a function. For simple detections, just passing
385 | * in a statement that will return a boolean value works just fine.
386 | *
387 | * ```js
388 | * Modernizr.addTest('hasjquery', 'jQuery' in window);
389 | * ```
390 | *
391 | * Just like before, when the above runs `Modernizr.hasjquery` will be true if
392 | * jQuery has been included on the page. Not using a function saves a small amount
393 | * of overhead for the browser, as well as making your code much more readable.
394 | *
395 | * Finally, you also have the ability to pass in an object of feature names and
396 | * their tests. This is handy if you want to add multiple detections in one go.
397 | * The keys should always be a string, and the value can be either a boolean or
398 | * function that returns a boolean.
399 | *
400 | * ```js
401 | * var detects = {
402 | * 'hasjquery': 'jQuery' in window,
403 | * 'itstuesday': function() {
404 | * var d = new Date();
405 | * return d.getDay() === 2;
406 | * }
407 | * }
408 | *
409 | * Modernizr.addTest(detects);
410 | * ```
411 | *
412 | * There is really no difference between the first methods and this one, it is
413 | * just a convenience to let you write more readable code.
414 | */
415 | function addTest(feature, test) {
416 |
417 | if (typeof feature === 'object') {
418 | for (var key in feature) {
419 | if (hasOwnProp(feature, key)) {
420 | addTest(key, feature[ key ]);
421 | }
422 | }
423 | } else {
424 |
425 | feature = feature.toLowerCase();
426 | var featureNameSplit = feature.split('.');
427 | var last = Modernizr[featureNameSplit[0]];
428 |
429 | // Again, we don't check for parent test existence. Get that right, though.
430 | if (featureNameSplit.length === 2) {
431 | last = last[featureNameSplit[1]];
432 | }
433 |
434 | if (typeof last !== 'undefined') {
435 | // we're going to quit if you're trying to overwrite an existing test
436 | // if we were to allow it, we'd do this:
437 | // var re = new RegExp("\\b(no-)?" + feature + "\\b");
438 | // docElement.className = docElement.className.replace( re, '' );
439 | // but, no rly, stuff 'em.
440 | return Modernizr;
441 | }
442 |
443 | test = typeof test === 'function' ? test() : test;
444 |
445 | // Set the value (this is the magic, right here).
446 | if (featureNameSplit.length === 1) {
447 | Modernizr[featureNameSplit[0]] = test;
448 | } else {
449 | // cast to a Boolean, if not one already
450 | if (Modernizr[featureNameSplit[0]] && !(Modernizr[featureNameSplit[0]] instanceof Boolean)) {
451 | Modernizr[featureNameSplit[0]] = new Boolean(Modernizr[featureNameSplit[0]]);
452 | }
453 |
454 | Modernizr[featureNameSplit[0]][featureNameSplit[1]] = test;
455 | }
456 |
457 | // Set a single class (either `feature` or `no-feature`)
458 | setClasses([(!!test && test !== false ? '' : 'no-') + featureNameSplit.join('-')]);
459 |
460 | // Trigger the event
461 | Modernizr._trigger(feature, test);
462 | }
463 |
464 | return Modernizr; // allow chaining.
465 | }
466 |
467 | // After all the tests are run, add self to the Modernizr prototype
468 | Modernizr._q.push(function() {
469 | ModernizrProto.addTest = addTest;
470 | });
471 |
472 |
473 |
474 |
475 | /**
476 | * @optionName html5printshiv
477 | * @optionProp html5printshiv
478 | */
479 |
480 | // Take the html5 variable out of the html5shiv scope so we can return it.
481 | var html5;
482 | if (!isSVG) {
483 | /**
484 | * @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
485 | */
486 | ;(function(window, document) {
487 | /*jshint evil:true */
488 | /** version */
489 | var version = '3.7.3';
490 |
491 | /** Preset options */
492 | var options = window.html5 || {};
493 |
494 | /** Used to skip problem elements */
495 | var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
496 |
497 | /** Not all elements can be cloned in IE **/
498 | var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
499 |
500 | /** Detect whether the browser supports default html5 styles */
501 | var supportsHtml5Styles;
502 |
503 | /** Name of the expando, to work with multiple documents or to re-shiv one document */
504 | var expando = '_html5shiv';
505 |
506 | /** The id for the the documents expando */
507 | var expanID = 0;
508 |
509 | /** Cached data for each document */
510 | var expandoData = {};
511 |
512 | /** Detect whether the browser supports unknown elements */
513 | var supportsUnknownElements;
514 |
515 | (function() {
516 | try {
517 | var a = document.createElement('a');
518 | a.innerHTML = '';
519 | //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
520 | supportsHtml5Styles = ('hidden' in a);
521 |
522 | supportsUnknownElements = a.childNodes.length == 1 || (function() {
523 | // assign a false positive if unable to shiv
524 | (document.createElement)('a');
525 | var frag = document.createDocumentFragment();
526 | return (
527 | typeof frag.cloneNode == 'undefined' ||
528 | typeof frag.createDocumentFragment == 'undefined' ||
529 | typeof frag.createElement == 'undefined'
530 | );
531 | }());
532 | } catch(e) {
533 | // assign a false positive if detection fails => unable to shiv
534 | supportsHtml5Styles = true;
535 | supportsUnknownElements = true;
536 | }
537 |
538 | }());
539 |
540 | /*--------------------------------------------------------------------------*/
541 |
542 | /**
543 | * Creates a style sheet with the given CSS text and adds it to the document.
544 | * @private
545 | * @param {Document} ownerDocument The document.
546 | * @param {String} cssText The CSS text.
547 | * @returns {StyleSheet} The style element.
548 | */
549 | function addStyleSheet(ownerDocument, cssText) {
550 | var p = ownerDocument.createElement('p'),
551 | parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
552 |
553 | p.innerHTML = 'x';
554 | return parent.insertBefore(p.lastChild, parent.firstChild);
555 | }
556 |
557 | /**
558 | * Returns the value of `html5.elements` as an array.
559 | * @private
560 | * @returns {Array} An array of shived element node names.
561 | */
562 | function getElements() {
563 | var elements = html5.elements;
564 | return typeof elements == 'string' ? elements.split(' ') : elements;
565 | }
566 |
567 | /**
568 | * Extends the built-in list of html5 elements
569 | * @memberOf html5
570 | * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
571 | * @param {Document} ownerDocument The context document.
572 | */
573 | function addElements(newElements, ownerDocument) {
574 | var elements = html5.elements;
575 | if(typeof elements != 'string'){
576 | elements = elements.join(' ');
577 | }
578 | if(typeof newElements != 'string'){
579 | newElements = newElements.join(' ');
580 | }
581 | html5.elements = elements +' '+ newElements;
582 | shivDocument(ownerDocument);
583 | }
584 |
585 | /**
586 | * Returns the data associated to the given document
587 | * @private
588 | * @param {Document} ownerDocument The document.
589 | * @returns {Object} An object of data.
590 | */
591 | function getExpandoData(ownerDocument) {
592 | var data = expandoData[ownerDocument[expando]];
593 | if (!data) {
594 | data = {};
595 | expanID++;
596 | ownerDocument[expando] = expanID;
597 | expandoData[expanID] = data;
598 | }
599 | return data;
600 | }
601 |
602 | /**
603 | * returns a shived element for the given nodeName and document
604 | * @memberOf html5
605 | * @param {String} nodeName name of the element
606 | * @param {Document} ownerDocument The context document.
607 | * @returns {Object} The shived element.
608 | */
609 | function createElement(nodeName, ownerDocument, data){
610 | if (!ownerDocument) {
611 | ownerDocument = document;
612 | }
613 | if(supportsUnknownElements){
614 | return ownerDocument.createElement(nodeName);
615 | }
616 | if (!data) {
617 | data = getExpandoData(ownerDocument);
618 | }
619 | var node;
620 |
621 | if (data.cache[nodeName]) {
622 | node = data.cache[nodeName].cloneNode();
623 | } else if (saveClones.test(nodeName)) {
624 | node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
625 | } else {
626 | node = data.createElem(nodeName);
627 | }
628 |
629 | // Avoid adding some elements to fragments in IE < 9 because
630 | // * Attributes like `name` or `type` cannot be set/changed once an element
631 | // is inserted into a document/fragment
632 | // * Link elements with `src` attributes that are inaccessible, as with
633 | // a 403 response, will cause the tab/window to crash
634 | // * Script elements appended to fragments will execute when their `src`
635 | // or `text` property is set
636 | return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
637 | }
638 |
639 | /**
640 | * returns a shived DocumentFragment for the given document
641 | * @memberOf html5
642 | * @param {Document} ownerDocument The context document.
643 | * @returns {Object} The shived DocumentFragment.
644 | */
645 | function createDocumentFragment(ownerDocument, data){
646 | if (!ownerDocument) {
647 | ownerDocument = document;
648 | }
649 | if(supportsUnknownElements){
650 | return ownerDocument.createDocumentFragment();
651 | }
652 | data = data || getExpandoData(ownerDocument);
653 | var clone = data.frag.cloneNode(),
654 | i = 0,
655 | elems = getElements(),
656 | l = elems.length;
657 | for(;i+~])(' + getElements().join('|') + ')(?=[[\\s,>+~#.:]|$)', 'gi'),
884 | replacement = '$1' + shivNamespace + '\\:$2';
885 |
886 | while (index--) {
887 | pair = parts[index] = parts[index].split('}');
888 | pair[pair.length - 1] = pair[pair.length - 1].replace(reElements, replacement);
889 | parts[index] = pair.join('}');
890 | }
891 | return parts.join('{');
892 | }
893 |
894 | /**
895 | * Removes the given wrappers, leaving the original elements.
896 | * @private
897 | * @params {Array} wrappers An array of printable wrappers.
898 | */
899 | function removeWrappers(wrappers) {
900 | var index = wrappers.length;
901 | while (index--) {
902 | wrappers[index].removeNode();
903 | }
904 | }
905 |
906 | /*--------------------------------------------------------------------------*/
907 |
908 | /**
909 | * Shivs the given document for print.
910 | * @memberOf html5
911 | * @param {Document} ownerDocument The document to shiv.
912 | * @returns {Document} The shived document.
913 | */
914 | function shivPrint(ownerDocument) {
915 | var shivedSheet,
916 | wrappers,
917 | data = getExpandoData(ownerDocument),
918 | namespaces = ownerDocument.namespaces,
919 | ownerWindow = ownerDocument.parentWindow;
920 |
921 | if (!supportsShivableSheets || ownerDocument.printShived) {
922 | return ownerDocument;
923 | }
924 | if (typeof namespaces[shivNamespace] == 'undefined') {
925 | namespaces.add(shivNamespace);
926 | }
927 |
928 | function removeSheet() {
929 | clearTimeout(data._removeSheetTimer);
930 | if (shivedSheet) {
931 | shivedSheet.removeNode(true);
932 | }
933 | shivedSheet= null;
934 | }
935 |
936 | ownerWindow.attachEvent('onbeforeprint', function() {
937 |
938 | removeSheet();
939 |
940 | var imports,
941 | length,
942 | sheet,
943 | collection = ownerDocument.styleSheets,
944 | cssText = [],
945 | index = collection.length,
946 | sheets = Array(index);
947 |
948 | // convert styleSheets collection to an array
949 | while (index--) {
950 | sheets[index] = collection[index];
951 | }
952 | // concat all style sheet CSS text
953 | while ((sheet = sheets.pop())) {
954 | // IE does not enforce a same origin policy for external style sheets...
955 | // but has trouble with some dynamically created stylesheets
956 | if (!sheet.disabled && reMedia.test(sheet.media)) {
957 |
958 | try {
959 | imports = sheet.imports;
960 | length = imports.length;
961 | } catch(er){
962 | length = 0;
963 | }
964 |
965 | for (index = 0; index < length; index++) {
966 | sheets.push(imports[index]);
967 | }
968 |
969 | try {
970 | cssText.push(sheet.cssText);
971 | } catch(er){}
972 | }
973 | }
974 |
975 | // wrap all HTML5 elements with printable elements and add the shived style sheet
976 | cssText = shivCssText(cssText.reverse().join(''));
977 | wrappers = addWrappers(ownerDocument);
978 | shivedSheet = addStyleSheet(ownerDocument, cssText);
979 |
980 | });
981 |
982 | ownerWindow.attachEvent('onafterprint', function() {
983 | // remove wrappers, leaving the original elements, and remove the shived style sheet
984 | removeWrappers(wrappers);
985 | clearTimeout(data._removeSheetTimer);
986 | data._removeSheetTimer = setTimeout(removeSheet, 500);
987 | });
988 |
989 | ownerDocument.printShived = true;
990 | return ownerDocument;
991 | }
992 |
993 | /*--------------------------------------------------------------------------*/
994 |
995 | // expose API
996 | html5.type += ' print';
997 | html5.shivPrint = shivPrint;
998 |
999 | // shiv for print
1000 | shivPrint(document);
1001 |
1002 | if(typeof module == 'object' && module.exports){
1003 | module.exports = html5;
1004 | }
1005 |
1006 | }(typeof window !== "undefined" ? window : this, document));
1007 | }
1008 |
1009 | ;
1010 |
1011 | /**
1012 | * contains checks to see if a string contains another string
1013 | *
1014 | * @access private
1015 | * @function contains
1016 | * @param {string} str - The string we want to check for substrings
1017 | * @param {string} substr - The substring we want to search the first string for
1018 | * @returns {boolean} true if and only if the first string 'str' contains the second string 'substr'
1019 | */
1020 | function contains(str, substr) {
1021 | return !!~('' + str).indexOf(substr);
1022 | }
1023 |
1024 | ;
1025 |
1026 | /**
1027 | * createElement is a convenience wrapper around document.createElement. Since we
1028 | * use createElement all over the place, this allows for (slightly) smaller code
1029 | * as well as abstracting away issues with creating elements in contexts other than
1030 | * HTML documents (e.g. SVG documents).
1031 | *
1032 | * @access private
1033 | * @function createElement
1034 | * @returns {HTMLElement|SVGElement} An HTML or SVG element
1035 | */
1036 | function createElement() {
1037 | if (typeof document.createElement !== 'function') {
1038 | // This is the case in IE7, where the type of createElement is "object".
1039 | // For this reason, we cannot call apply() as Object is not a Function.
1040 | return document.createElement(arguments[0]);
1041 | } else if (isSVG) {
1042 | return document.createElementNS.call(document, 'http://www.w3.org/2000/svg', arguments[0]);
1043 | } else {
1044 | return document.createElement.apply(document, arguments);
1045 | }
1046 | }
1047 |
1048 | ;
1049 |
1050 | /**
1051 | * Create our "modernizr" element that we do most feature tests on.
1052 | *
1053 | * @access private
1054 | */
1055 | var modElem = {
1056 | elem: createElement('modernizr')
1057 | };
1058 |
1059 | // Clean up this element
1060 | Modernizr._q.push(function() {
1061 | delete modElem.elem;
1062 | });
1063 |
1064 |
1065 |
1066 | var mStyle = {
1067 | style: modElem.elem.style
1068 | };
1069 |
1070 | // kill ref for gc, must happen before mod.elem is removed, so we unshift on to
1071 | // the front of the queue.
1072 | Modernizr._q.unshift(function() {
1073 | delete mStyle.style;
1074 | });
1075 |
1076 |
1077 |
1078 | /**
1079 | * getBody returns the body of a document, or an element that can stand in for
1080 | * the body if a real body does not exist
1081 | *
1082 | * @access private
1083 | * @function getBody
1084 | * @returns {HTMLElement|SVGElement} Returns the real body of a document, or an
1085 | * artificially created element that stands in for the body
1086 | */
1087 | function getBody() {
1088 | // After page load injecting a fake body doesn't work so check if body exists
1089 | var body = document.body;
1090 |
1091 | if (!body) {
1092 | // Can't use the real body create a fake one.
1093 | body = createElement(isSVG ? 'svg' : 'body');
1094 | body.fake = true;
1095 | }
1096 |
1097 | return body;
1098 | }
1099 |
1100 | ;
1101 |
1102 | /**
1103 | * injectElementWithStyles injects an element with style element and some CSS rules
1104 | *
1105 | * @access private
1106 | * @function injectElementWithStyles
1107 | * @param {string} rule - String representing a css rule
1108 | * @param {Function} callback - A function that is used to test the injected element
1109 | * @param {number} [nodes] - An integer representing the number of additional nodes you want injected
1110 | * @param {string[]} [testnames] - An array of strings that are used as ids for the additional nodes
1111 | * @returns {boolean} the result of the specified callback test
1112 | */
1113 | function injectElementWithStyles(rule, callback, nodes, testnames) {
1114 | var mod = 'modernizr';
1115 | var style;
1116 | var ret;
1117 | var node;
1118 | var docOverflow;
1119 | var div = createElement('div');
1120 | var body = getBody();
1121 |
1122 | if (parseInt(nodes, 10)) {
1123 | // In order not to give false positives we create a node for each test
1124 | // This also allows the method to scale for unspecified uses
1125 | while (nodes--) {
1126 | node = createElement('div');
1127 | node.id = testnames ? testnames[nodes] : mod + (nodes + 1);
1128 | div.appendChild(node);
1129 | }
1130 | }
1131 |
1132 | style = createElement('style');
1133 | style.type = 'text/css';
1134 | style.id = 's' + mod;
1135 |
1136 | // IE6 will false positive on some tests due to the style element inside the test div somehow interfering offsetHeight, so insert it into body or fakebody.
1137 | // Opera will act all quirky when injecting elements in documentElement when page is served as xml, needs fakebody too. #270
1138 | (!body.fake ? div : body).appendChild(style);
1139 | body.appendChild(div);
1140 |
1141 | if (style.styleSheet) {
1142 | style.styleSheet.cssText = rule;
1143 | } else {
1144 | style.appendChild(document.createTextNode(rule));
1145 | }
1146 | div.id = mod;
1147 |
1148 | if (body.fake) {
1149 | //avoid crashing IE8, if background image is used
1150 | body.style.background = '';
1151 | //Safari 5.13/5.1.4 OSX stops loading if ::-webkit-scrollbar is used and scrollbars are visible
1152 | body.style.overflow = 'hidden';
1153 | docOverflow = docElement.style.overflow;
1154 | docElement.style.overflow = 'hidden';
1155 | docElement.appendChild(body);
1156 | }
1157 |
1158 | ret = callback(div, rule);
1159 | // If this is done after page load we don't want to remove the body so check if body exists
1160 | if (body.fake) {
1161 | body.parentNode.removeChild(body);
1162 | docElement.style.overflow = docOverflow;
1163 | // Trigger layout so kinetic scrolling isn't disabled in iOS6+
1164 | // eslint-disable-next-line
1165 | docElement.offsetHeight;
1166 | } else {
1167 | div.parentNode.removeChild(div);
1168 | }
1169 |
1170 | return !!ret;
1171 | }
1172 |
1173 | ;
1174 |
1175 | /**
1176 | * domToCSS takes a camelCase string and converts it to kebab-case
1177 | * e.g. boxSizing -> box-sizing
1178 | *
1179 | * @access private
1180 | * @function domToCSS
1181 | * @param {string} name - String name of camelCase prop we want to convert
1182 | * @returns {string} The kebab-case version of the supplied name
1183 | */
1184 | function domToCSS(name) {
1185 | return name.replace(/([A-Z])/g, function(str, m1) {
1186 | return '-' + m1.toLowerCase();
1187 | }).replace(/^ms-/, '-ms-');
1188 | }
1189 |
1190 | ;
1191 |
1192 |
1193 | /**
1194 | * wrapper around getComputedStyle, to fix issues with Firefox returning null when
1195 | * called inside of a hidden iframe
1196 | *
1197 | * @access private
1198 | * @function computedStyle
1199 | * @param {HTMLElement|SVGElement} elem - The element we want to find the computed styles of
1200 | * @param {string|null} [pseudo] - An optional pseudo element selector (e.g. :before), of null if none
1201 | * @param {string} prop - A CSS property
1202 | * @returns {CSSStyleDeclaration} the value of the specified CSS property
1203 | */
1204 | function computedStyle(elem, pseudo, prop) {
1205 | var result;
1206 |
1207 | if ('getComputedStyle' in window) {
1208 | result = getComputedStyle.call(window, elem, pseudo);
1209 | var console = window.console;
1210 |
1211 | if (result !== null) {
1212 | if (prop) {
1213 | result = result.getPropertyValue(prop);
1214 | }
1215 | } else {
1216 | if (console) {
1217 | var method = console.error ? 'error' : 'log';
1218 | console[method].call(console, 'getComputedStyle returning null, its possible modernizr test results are inaccurate');
1219 | }
1220 | }
1221 | } else {
1222 | result = !pseudo && elem.currentStyle && elem.currentStyle[prop];
1223 | }
1224 |
1225 | return result;
1226 | }
1227 |
1228 | ;
1229 |
1230 | /**
1231 | * nativeTestProps allows for us to use native feature detection functionality if available.
1232 | * some prefixed form, or false, in the case of an unsupported rule
1233 | *
1234 | * @access private
1235 | * @function nativeTestProps
1236 | * @param {Array} props - An array of property names
1237 | * @param {string} value - A string representing the value we want to check via @supports
1238 | * @returns {boolean|undefined} A boolean when @supports exists, undefined otherwise
1239 | */
1240 | // Accepts a list of property names and a single value
1241 | // Returns `undefined` if native detection not available
1242 | function nativeTestProps(props, value) {
1243 | var i = props.length;
1244 | // Start with the JS API: https://www.w3.org/TR/css3-conditional/#the-css-interface
1245 | if ('CSS' in window && 'supports' in window.CSS) {
1246 | // Try every prefixed variant of the property
1247 | while (i--) {
1248 | if (window.CSS.supports(domToCSS(props[i]), value)) {
1249 | return true;
1250 | }
1251 | }
1252 | return false;
1253 | }
1254 | // Otherwise fall back to at-rule (for Opera 12.x)
1255 | else if ('CSSSupportsRule' in window) {
1256 | // Build a condition string for every prefixed variant
1257 | var conditionText = [];
1258 | while (i--) {
1259 | conditionText.push('(' + domToCSS(props[i]) + ':' + value + ')');
1260 | }
1261 | conditionText = conditionText.join(' or ');
1262 | return injectElementWithStyles('@supports (' + conditionText + ') { #modernizr { position: absolute; } }', function(node) {
1263 | return computedStyle(node, null, 'position') === 'absolute';
1264 | });
1265 | }
1266 | return undefined;
1267 | }
1268 | ;
1269 |
1270 | /**
1271 | * cssToDOM takes a kebab-case string and converts it to camelCase
1272 | * e.g. box-sizing -> boxSizing
1273 | *
1274 | * @access private
1275 | * @function cssToDOM
1276 | * @param {string} name - String name of kebab-case prop we want to convert
1277 | * @returns {string} The camelCase version of the supplied name
1278 | */
1279 | function cssToDOM(name) {
1280 | return name.replace(/([a-z])-([a-z])/g, function(str, m1, m2) {
1281 | return m1 + m2.toUpperCase();
1282 | }).replace(/^-/, '');
1283 | }
1284 |
1285 | ;
1286 |
1287 | // testProps is a generic CSS / DOM property test.
1288 |
1289 | // In testing support for a given CSS property, it's legit to test:
1290 | // `elem.style[styleName] !== undefined`
1291 | // If the property is supported it will return an empty string,
1292 | // if unsupported it will return undefined.
1293 |
1294 | // We'll take advantage of this quick test and skip setting a style
1295 | // on our modernizr element, but instead just testing undefined vs
1296 | // empty string.
1297 |
1298 | // Property names can be provided in either camelCase or kebab-case.
1299 |
1300 | function testProps(props, prefixed, value, skipValueTest) {
1301 | skipValueTest = is(skipValueTest, 'undefined') ? false : skipValueTest;
1302 |
1303 | // Try native detect first
1304 | if (!is(value, 'undefined')) {
1305 | var result = nativeTestProps(props, value);
1306 | if (!is(result, 'undefined')) {
1307 | return result;
1308 | }
1309 | }
1310 |
1311 | // Otherwise do it properly
1312 | var afterInit, i, propsLength, prop, before;
1313 |
1314 | // If we don't have a style element, that means we're running async or after
1315 | // the core tests, so we'll need to create our own elements to use.
1316 |
1317 | // Inside of an SVG element, in certain browsers, the `style` element is only
1318 | // defined for valid tags. Therefore, if `modernizr` does not have one, we
1319 | // fall back to a less used element and hope for the best.
1320 | // For strict XHTML browsers the hardly used samp element is used.
1321 | var elems = ['modernizr', 'tspan', 'samp'];
1322 | while (!mStyle.style && elems.length) {
1323 | afterInit = true;
1324 | mStyle.modElem = createElement(elems.shift());
1325 | mStyle.style = mStyle.modElem.style;
1326 | }
1327 |
1328 | // Delete the objects if we created them.
1329 | function cleanElems() {
1330 | if (afterInit) {
1331 | delete mStyle.style;
1332 | delete mStyle.modElem;
1333 | }
1334 | }
1335 |
1336 | propsLength = props.length;
1337 | for (i = 0; i < propsLength; i++) {
1338 | prop = props[i];
1339 | before = mStyle.style[prop];
1340 |
1341 | if (contains(prop, '-')) {
1342 | prop = cssToDOM(prop);
1343 | }
1344 |
1345 | if (mStyle.style[prop] !== undefined) {
1346 |
1347 | // If value to test has been passed in, do a set-and-check test.
1348 | // 0 (integer) is a valid property value, so check that `value` isn't
1349 | // undefined, rather than just checking it's truthy.
1350 | if (!skipValueTest && !is(value, 'undefined')) {
1351 |
1352 | // Needs a try catch block because of old IE. This is slow, but will
1353 | // be avoided in most cases because `skipValueTest` will be used.
1354 | try {
1355 | mStyle.style[prop] = value;
1356 | } catch (e) {}
1357 |
1358 | // If the property value has changed, we assume the value used is
1359 | // supported. If `value` is empty string, it'll fail here (because
1360 | // it hasn't changed), which matches how browsers have implemented
1361 | // CSS.supports()
1362 | if (mStyle.style[prop] !== before) {
1363 | cleanElems();
1364 | return prefixed === 'pfx' ? prop : true;
1365 | }
1366 | }
1367 | // Otherwise just return true, or the property name if this is a
1368 | // `prefixed()` call
1369 | else {
1370 | cleanElems();
1371 | return prefixed === 'pfx' ? prop : true;
1372 | }
1373 | }
1374 | }
1375 | cleanElems();
1376 | return false;
1377 | }
1378 |
1379 | ;
1380 |
1381 | /**
1382 | * testProp() investigates whether a given style property is recognized
1383 | * Property names can be provided in either camelCase or kebab-case.
1384 | *
1385 | * @memberOf Modernizr
1386 | * @name Modernizr.testProp
1387 | * @access public
1388 | * @optionName Modernizr.testProp()
1389 | * @optionProp testProp
1390 | * @function testProp
1391 | * @param {string} prop - Name of the CSS property to check
1392 | * @param {string} [value] - Name of the CSS value to check
1393 | * @param {boolean} [useValue] - Whether or not to check the value if @supports isn't supported
1394 | * @returns {boolean} an empty string if the property is supported, undefined if its unsupported
1395 | * @example
1396 | *
1397 | * Just like [testAllProps](#modernizr-testallprops), only it does not check any vendor prefixed
1398 | * version of the string.
1399 | *
1400 | * Note that the property name must be provided in camelCase (e.g. boxSizing not box-sizing)
1401 | *
1402 | * ```js
1403 | * Modernizr.testProp('pointerEvents') // true
1404 | * ```
1405 | *
1406 | * You can also provide a value as an optional second argument to check if a
1407 | * specific value is supported
1408 | *
1409 | * ```js
1410 | * Modernizr.testProp('pointerEvents', 'none') // true
1411 | * Modernizr.testProp('pointerEvents', 'penguin') // false
1412 | * ```
1413 | */
1414 | var testProp = ModernizrProto.testProp = function(prop, value, useValue) {
1415 | return testProps([prop], undefined, value, useValue);
1416 | };
1417 |
1418 |
1419 | /*!
1420 | {
1421 | "name": "CSS Supports",
1422 | "property": "supports",
1423 | "caniuse": "css-featurequeries",
1424 | "tags": ["css"],
1425 | "builderAliases": ["css_supports"],
1426 | "notes": [{
1427 | "name": "W3C Spec (The @supports rule)",
1428 | "href": "https://dev.w3.org/csswg/css3-conditional/#at-supports"
1429 | }, {
1430 | "name": "Related Github Issue",
1431 | "href": "https://github.com/Modernizr/Modernizr/issues/648"
1432 | }, {
1433 | "name": "W3C Spec (The CSSSupportsRule interface)",
1434 | "href": "https://dev.w3.org/csswg/css3-conditional/#the-csssupportsrule-interface"
1435 | }]
1436 | }
1437 | !*/
1438 |
1439 | var newSyntax = 'CSS' in window && 'supports' in window.CSS;
1440 | var oldSyntax = 'supportsCSS' in window;
1441 | Modernizr.addTest('supports', newSyntax || oldSyntax);
1442 |
1443 |
1444 | // Run each test
1445 | testRunner();
1446 |
1447 | // Remove the "no-js" class if it exists
1448 | setClasses(classes);
1449 |
1450 | delete ModernizrProto.addTest;
1451 | delete ModernizrProto.addAsyncTest;
1452 |
1453 | // Run the things that are supposed to run after the tests
1454 | for (var i = 0; i < Modernizr._q.length; i++) {
1455 | Modernizr._q[i]();
1456 | }
1457 |
1458 | // Leak Modernizr namespace
1459 | scriptGlobalObject.Modernizr = Modernizr;
1460 |
1461 |
1462 | ;
1463 |
1464 | })(window, window, document);
1465 |
--------------------------------------------------------------------------------
/assets/scss/app.scss:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 |
4 | @import 'utilities/*';
5 | @import 'components/*';
6 | @import 'base';
7 |
8 | @tailwind utilities;
--------------------------------------------------------------------------------
/assets/scss/base.scss:
--------------------------------------------------------------------------------
1 | // Font Face
2 | // @include font-face('family', 'filename', 500, 'normal');
3 |
4 | // Body
5 |
6 | html {
7 | @apply text-base;
8 | }
9 |
10 | body {
11 | @apply
12 | font-sans-primary
13 | text-gray-800
14 | text-optimize-legibility
15 | antialiased;
16 | }
17 |
18 | // Links
19 |
20 | a {
21 | @apply transition--default;
22 | }
23 |
24 | // Typography
25 |
26 | p {
27 | @apply mb-4;
28 | &:last-of-type {
29 | @apply mb-0;
30 | }
31 | }
32 |
33 | // Selection
34 |
35 | ::selection {
36 | @apply
37 | text-primary-500
38 | bg-primary-100;
39 | }
40 |
41 | // FOUT fix
42 |
43 | .wf-loading {
44 | @apply invisible;
45 | }
46 |
47 | .wf-active,
48 | .wf-inactive {
49 | @apply visible;
50 | }
51 |
--------------------------------------------------------------------------------
/assets/scss/components/alpinejs.scss:
--------------------------------------------------------------------------------
1 | [x-cloak] {
2 | @apply hidden;
3 | }
--------------------------------------------------------------------------------
/assets/scss/components/links.scss:
--------------------------------------------------------------------------------
1 | .link {
2 | @apply transition--default;
3 | &--primary {
4 | @apply
5 | text-primary-500
6 | underline;
7 | &:hover,
8 | &:active {
9 | @apply text-primary-700;
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/assets/scss/utilities/font-face.scss:
--------------------------------------------------------------------------------
1 | $font-path: '../fonts';
2 |
3 | @mixin font-face($family, $filename, $weight, $style) {
4 |
5 | $weight: '400' !default;
6 | $style: 'normal' !default;
7 |
8 | @font-face {
9 | font-family: "#{$family}";
10 | src: url("#{$font-path}/#{$filename}.eot");
11 | src: local("#{$family}"),
12 | url("#{$font-path}/#{$filename}.eot?#iefix") format("embedded-opentype"),
13 | url("#{$font-path}/#{$filename}.woff2") format("woff2"),
14 | url("#{$font-path}/#{$filename}.woff") format("woff"),
15 | url("#{$font-path}/#{$filename}.ttf") format("truetype"),
16 | url("#{$font-path}/#{$filename}.svg##{$filename}") format("svg");
17 | font-weight: $weight;
18 | font-style: $style;
19 | font-display: swap;
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/assets/scss/utilities/rem.scss:
--------------------------------------------------------------------------------
1 | @function rem($size) {
2 | $remSize: $size / 16;
3 | @return #{$remSize}rem;
4 | }
5 |
--------------------------------------------------------------------------------
/assets/scss/utilities/transition.scss:
--------------------------------------------------------------------------------
1 | .transition {
2 | &--default {
3 | @apply
4 | transition-all
5 | duration-500
6 | ease-out;
7 | }
8 | }
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const package = require("./package.json");
2 |
3 | const gulp = require("gulp");
4 | const sass = require("gulp-sass");
5 | const postcss = require("gulp-postcss");
6 | const tailwindcss = require("tailwindcss");
7 | const browsersync = require("browser-sync").create();
8 | const sassglob = require("gulp-sass-glob");
9 | const sourcemaps = require("gulp-sourcemaps");
10 | const autoprefixer = require("autoprefixer");
11 | const cssnano = require("cssnano");
12 | const newer = require("gulp-newer");
13 | const imagemin = require("gulp-imagemin");
14 | const minify = require("gulp-minify");
15 | const modernizr = require("gulp-modernizr");
16 | const purgecss = require("gulp-purgecss");
17 | const concat = require("gulp-concat");
18 | const favicons = require("favicons").stream;
19 | const rev = require("gulp-rev");
20 | const revDel = require("rev-del");
21 | const plumber = require("gulp-plumber");
22 | const notify = require("gulp-notify");
23 | const del = require("del");
24 | const critical = require("critical");
25 | const clean = require("gulp-dest-clean");
26 |
27 | function browserSync(done) {
28 |
29 | if (package.env.local === "") {
30 | browsersync.init({
31 | server: {
32 | baseDir: package.paths.public
33 | }
34 | });
35 | }
36 | else {
37 | browsersync.init({
38 | proxy: package.env.local
39 | });
40 | }
41 | done();
42 |
43 | }
44 |
45 | function browserSyncReload(done) {
46 |
47 | browsersync.reload();
48 | done();
49 |
50 | }
51 |
52 | function css() {
53 |
54 | const cssFiles = [
55 | package.paths.assets.scss + package.files.assets.scss
56 | ];
57 |
58 | for (var i = 0; i < package.cssDependencies.length; i++) {
59 | cssFiles.unshift(package.paths.dependencies + package.cssDependencies[i]);
60 | }
61 |
62 | const plugins = [
63 | tailwindcss(package.files.tailwind),
64 | autoprefixer(),
65 | cssnano()
66 | ];
67 |
68 | return gulp
69 | .src(cssFiles)
70 | .pipe(plumber({ errorHandler: notify.onError("Error [css]: <%= error.message %>") }))
71 | .pipe(concat(package.files.dist.css))
72 | .pipe(sourcemaps.init())
73 | .pipe(sassglob())
74 | .pipe(sass())
75 | .pipe(postcss(plugins))
76 | .pipe(sourcemaps.write("/"))
77 | .pipe(gulp.dest(package.paths.public + package.paths.dist.css))
78 | .pipe(browsersync.stream());
79 |
80 | }
81 |
82 | function js() {
83 |
84 | const jsArray = [];
85 |
86 | const jsFiles = [
87 | "modernizr.js",
88 | "components/**/*.js",
89 | package.files.assets.js
90 | ];
91 |
92 | for (var i = 0; i < package.jsDependencies.length; i++) {
93 | jsArray.push(package.paths.dependencies + package.jsDependencies[i]);
94 | }
95 |
96 | for (var i = 0; i < jsFiles.length; i++) {
97 | jsArray.push(package.paths.assets.js + jsFiles[i]);
98 | }
99 |
100 | return gulp
101 | .src(jsArray)
102 | .pipe(plumber({ errorHandler: notify.onError("Error [js]: <%= error.message %>") }))
103 | .pipe(concat(package.files.dist.js))
104 | .pipe(sourcemaps.init())
105 | .pipe(
106 | minify(
107 | {
108 | ext:{
109 | min:".js"
110 | },
111 | noSource: true
112 | }
113 | )
114 | )
115 | .pipe(sourcemaps.write("/"))
116 | .pipe(gulp.dest(package.paths.public + package.paths.dist.js))
117 | .pipe(browsersync.stream());
118 | }
119 |
120 | function images() {
121 |
122 | return gulp
123 | .src(package.paths.assets.images + "**/*")
124 | .pipe(plumber({ errorHandler: notify.onError("Error [images]: <%= error.message %>") }))
125 | .pipe(clean(package.paths.public + package.paths.dist.images, 'favicon/**'))
126 | .pipe(newer(package.paths.public + package.paths.dist.images))
127 | .pipe(
128 | imagemin(
129 | [
130 | imagemin.gifsicle({ interlaced: true }),
131 | imagemin.jpegtran({ progressive: true }),
132 | imagemin.optipng({ optimizationLevel: 5 }),
133 | imagemin.svgo({
134 | plugins: [
135 | { removeViewBox: true },
136 | { cleanupIDs: false }
137 | ]
138 | })
139 | ],
140 | { verbose: true }
141 | )
142 | )
143 | .pipe(gulp.dest(package.paths.public + package.paths.dist.images));
144 |
145 | }
146 |
147 | function favicon() {
148 |
149 | return gulp
150 | .src(package.paths.assets.images + "favicon.{jpg,png}")
151 | .pipe(plumber({ errorHandler: notify.onError("Error [favicon]: <%= error.message %>") }))
152 | .pipe(newer(package.paths.public + package.paths.dist.images + "favicon.{jpg,png}"))
153 | .pipe(
154 | favicons(
155 | {
156 | appName: package.name,
157 | appDescription: package.description,
158 | developerName: package.author,
159 | developerURL: package.authorUrl,
160 | background: "#FFF",
161 | display: "standalone",
162 | orientation: "any",
163 | version: 1.0,
164 | html: "favicons.html",
165 | pipeHTML: true,
166 | replace: true,
167 | path: "/" + package.paths.dist.favicon,
168 | icons: {
169 | favicons: true,
170 | android: true,
171 | appleIcon: true,
172 | firefox: true,
173 | windows: true,
174 | appleStartup: false,
175 | coast: false,
176 | opengraph: false,
177 | twitter: false,
178 | yandex: false
179 | }
180 | }
181 | )
182 | )
183 | .pipe(gulp.dest(package.paths.public + package.paths.dist.favicon));
184 |
185 | }
186 |
187 | function faviconHtml() {
188 | return gulp
189 | .src(
190 | package.paths.public + package.paths.dist.favicon + "favicons.html"
191 | )
192 | .pipe(
193 | gulp.dest(package.paths.templates + "_components/")
194 | );
195 | }
196 |
197 | function purgeCss() {
198 |
199 | class TailwindExtractor {
200 | static extract(content) {
201 | return content.match(/[A-z0-9-:\/]+/g);
202 | }
203 | }
204 |
205 | var whitelistPatterns = [];
206 | for (i = 0; i < package.purgeCss.whitelistPatterns.length; i++) {
207 | whitelistPatterns.push(new RegExp(package.purgeCss.whitelistPatterns[i], ""));
208 | }
209 |
210 | return gulp
211 | .src(package.paths.public + package.paths.dist.css + package.files.dist.css)
212 | .pipe(plumber({ errorHandler: notify.onError("Error [purgeCss]: <%= error.message %>") }))
213 | .pipe(
214 | purgecss({
215 | content: [
216 | package.paths.templates + "**/*.{html,twig,vue}",
217 | package.paths.public + package.paths.dist.base + "**/*.{js}"
218 | ],
219 | whitelistPatterns: whitelistPatterns,
220 | whitelistPatternsChildren: whitelistPatterns,
221 | extractors: [
222 | {
223 | extractor: TailwindExtractor,
224 | extensions: ["html", "twig", "vue"]
225 | }
226 | ]
227 | })
228 | )
229 | .pipe(gulp.dest(package.paths.public + package.paths.dist.css));
230 |
231 | }
232 |
233 | function doSynchronousLoop(data, processData, done) {
234 |
235 | if (data.length > 0) {
236 | const loop = (data, i, processData, done) => {
237 | processData(data[i], i, () => {
238 | if (++i < data.length) {
239 | loop(data, i, processData, done);
240 | } else {
241 | done();
242 | }
243 | });
244 | };
245 | loop(data, 0, processData, done);
246 | } else {
247 | done();
248 | }
249 |
250 | }
251 |
252 | const processCriticalCSS = (element, i, callback) => {
253 |
254 | critical
255 | .generate({
256 | src: package.critical.url + element.url,
257 | dest: package.templates + element.path + element.slug + "-critical.css",
258 | inline: false,
259 | ignore: [],
260 | bbase: "./",
261 | pathPrefix: "/",
262 | css: [package.files.dist.css],
263 | width: 1400,
264 | height: 900,
265 | minify: true,
266 | timeout: 60000
267 | },
268 | (err, output) => {
269 | if (err) {
270 | notify({
271 | message: "Error [processCriticalCSS]: " + err
272 | })
273 | }
274 | callback();
275 | }
276 | );
277 |
278 | }
279 |
280 | function criticalCss(done) {
281 |
282 | doSynchronousLoop(
283 | package.critical.elements,
284 | processCriticalCSS,
285 | () => {
286 | done();
287 | }
288 | );
289 |
290 | }
291 |
292 | function revCssJs(done) {
293 |
294 | return gulp
295 | .src(
296 | [
297 | package.paths.public + package.paths.dist.css + package.files.dist.css,
298 | package.paths.public + package.paths.dist.js + package.files.dist.js
299 | ],
300 | {
301 | base: package.paths.public + package.paths.dist.base
302 | }
303 | )
304 | .pipe(rev())
305 | .pipe(gulp.dest(package.paths.public + package.paths.dist.base))
306 | .pipe(rev.manifest(
307 | {
308 | base: "./"
309 | }
310 | ))
311 | .pipe(revDel(
312 | {
313 | oldManifest: "./rev-manifest.json",
314 | dest: package.paths.public + package.paths.dist.base
315 | }
316 | ))
317 | .pipe(gulp.dest("./"));
318 |
319 | }
320 |
321 | function browserFeatures() {
322 |
323 | return gulp
324 | .src(package.paths.assets.js + "**/*")
325 | .pipe(modernizr())
326 | .pipe(gulp.dest(package.paths.assets.js));
327 |
328 | }
329 |
330 | function watch(done) {
331 |
332 | gulp.watch(
333 | [
334 | "package.json",
335 | package.files.tailwind,
336 | package.paths.assets.scss + "**/*",
337 | ],
338 | css
339 | );
340 |
341 | gulp.watch(
342 | [
343 | "package.json",
344 | package.paths.assets.js + "**/*"
345 | ],
346 | js
347 | );
348 |
349 | gulp.watch(package.paths.public + "**/*", browserSyncReload);
350 |
351 | gulp.watch(package.paths.templates + "**/*.{html,twig,vue}", browserSyncReload);
352 |
353 | gulp.watch(package.paths.assets.images + "**/*", images);
354 |
355 | done();
356 |
357 | }
358 |
359 | exports.browserSync = browserSync;
360 | exports.browserSyncReload = browserSyncReload;
361 | exports.css = css;
362 | exports.js = js;
363 | exports.images = images;
364 | exports.favicon = favicon;
365 | exports.faviconHtml = faviconHtml;
366 | exports.purgeCss = purgeCss;
367 | exports.criticalCss = criticalCss;
368 | exports.revCssJs = revCssJs;
369 | exports.browserFeatures = browserFeatures;
370 | exports.watch = watch;
371 |
372 | exports.dev = gulp.series(browserFeatures, css, js, images, watch, browserSync);
373 | exports.production = gulp.series(
374 | gulp.parallel(browserFeatures, css, js),
375 | purgeCss,
376 | criticalCss,
377 | revCssJs,
378 | favicon,
379 | faviconHtml,
380 | images
381 | );
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Tailwind",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "gulpfile.js",
6 | "env": {
7 | "local": ""
8 | },
9 | "paths": {
10 | "dependencies": "node_modules/",
11 | "public": "web/",
12 | "templates": "templates/",
13 | "dist": {
14 | "base": "dist/",
15 | "css": "dist/css/",
16 | "js": "dist/js/",
17 | "images": "dist/images/",
18 | "favicon": "dist/images/favicon/"
19 | },
20 | "assets": {
21 | "scss": "assets/scss/",
22 | "js": "assets/js/",
23 | "images": "assets/images/",
24 | "fonts": "assets/fonts/"
25 | }
26 | },
27 | "files": {
28 | "tailwind": "./tailwind.config.js",
29 | "dist": {
30 | "css": "app.css",
31 | "js": "app.js"
32 | },
33 | "assets": {
34 | "scss": "app.scss",
35 | "js": "app.js"
36 | }
37 | },
38 | "critical": {
39 | "url": "http://tailwind-css.local/",
40 | "elements": [
41 | {
42 | "uri": "",
43 | "slug": "",
44 | "path": ""
45 | }
46 | ]
47 | },
48 | "purgeCss": {
49 | "whitelistPatterns": [
50 | "is-.*",
51 | "aos.*",
52 | "choices.*",
53 | "flickity.*",
54 | "mfp.*"
55 | ]
56 | },
57 | "cssDependencies": [],
58 | "jsDependencies": [
59 | "fg-loadcss/dist/cssrelpreload.js",
60 | "alpinejs/dist/alpine.js"
61 | ],
62 | "dependencies": {
63 | "alpinejs": "^2.3.5",
64 | "fg-loadcss": "^2.1.0",
65 | "tailwindcss": "^1.4.6",
66 | "tailwindcss-animations": "^2.0.0",
67 | "tailwindcss-aspect-ratio": "^2.0.0",
68 | "tailwindcss-typography": "^3.1.0"
69 | },
70 | "devDependencies": {
71 | "autoprefixer": "^9.8.0",
72 | "browser-sync": "^2.26.7",
73 | "critical": "^1.3.9",
74 | "cssnano": "^4.1.10",
75 | "del": "^4.1.1",
76 | "favicons": "^5.5.0",
77 | "gulp": "^4.0.2",
78 | "gulp-concat": "^2.6.1",
79 | "gulp-dest-clean": "^0.5.0",
80 | "gulp-imagemin": "^5.0.3",
81 | "gulp-minify": "^3.1.0",
82 | "gulp-modernizr": "^3.4.1",
83 | "gulp-newer": "^1.4.0",
84 | "gulp-notify": "^3.2.0",
85 | "gulp-plumber": "^1.2.1",
86 | "gulp-postcss": "^8.0.0",
87 | "gulp-purgecss": "^1.2.0",
88 | "gulp-rev": "^9.0.0",
89 | "gulp-sass": "^4.1.0",
90 | "gulp-sass-glob": "^1.1.0",
91 | "gulp-sourcemaps": "^2.6.5",
92 | "node-sass": "^4.14.1",
93 | "purgecss": "^1.4.2",
94 | "rev-del": "^2.0.0"
95 | },
96 | "scripts": {
97 | "dev": "gulp dev",
98 | "production": "gulp production"
99 | },
100 | "repository": {
101 | "type": "git",
102 | "url": "git+https://github.com/madebyshape/tailwind-css.git"
103 | },
104 | "author": "Jason Mayo (@bymayo)",
105 | "authorUrl": "https://madebyshape.co.uk",
106 | "license": "ISC",
107 | "bugs": {
108 | "url": "https://github.com/madebyshape/tailwind-css/issues"
109 | },
110 | "homepage": "https://github.com/madebyshape/tailwind-css#readme"
111 | }
112 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const defaultTheme = require('tailwindcss/defaultTheme');
2 | const alpha = { 100: 'FF', 90: 'E6', 80: 'CC', 70: 'B3', 60: '99', 50: '80', 40: '66', 30: '4D', 20: '33', 10: '1A' };
3 |
4 | module.exports = {
5 | theme: {
6 | extend: {
7 | colors: {
8 | primary: {
9 | 100: '#F0F2FD',
10 | 200: '#D9DFFA',
11 | 300: '#C2CBF7',
12 | 400: '#94A5F0',
13 | 500: '#667EEA',
14 | 600: '#5C71D3',
15 | 700: '#3D4C8C',
16 | 800: '#2E3969',
17 | 900: '#1F2646'
18 | },
19 | secondary: {
20 | 100: '#EBF7F7',
21 | 200: '#CDECEA',
22 | 300: '#AFE0DE',
23 | 400: '#74C9C5',
24 | 500: '#38B2AC',
25 | 600: '#32A09B',
26 | 700: '#226B67',
27 | 800: '#19504D',
28 | 900: '#113534'
29 | },
30 | brands: {
31 | facebook: '#3b5998',
32 | twitter: '#55acee',
33 | instagram: '#3f729b',
34 | linkedin: '#0976b4',
35 | youtube: '#e52d27',
36 | vimeo: '#1ab7ea',
37 | pinterest: '#cc2127'
38 | }
39 | },
40 | fontSize: theme => ({
41 | 'xs': ['0.75rem', theme('lineHeight.normal')], // 12
42 | 'sm': ['0.875rem', theme('lineHeight.normal')], // 14
43 | 'base': ['1rem', theme('lineHeight.normal')], // 16
44 | 'md': ['1.125rem', theme('lineHeight.normal')], // 18
45 | 'lg': ['1.25rem', theme('lineHeight.normal')], // 20
46 | 'xl': ['1.5rem', theme('lineHeight.normal')], // 24
47 | '2xl': ['1.875rem', theme('lineHeight.normal')], // 30
48 | '3xl': ['2.25rem', theme('lineHeight.normal')], // 36
49 | '4xl': ['3rem', theme('lineHeight.normal')], // 48
50 | '5xl': ['4rem', theme('lineHeight.normal')], // 64
51 | '6xl': ['4.5rem', theme('lineHeight.normal')] // 72
52 | }),
53 | fontFamily: {
54 | 'sans-primary': [
55 | ...defaultTheme.fontFamily.sans
56 | ],
57 | 'serif-primary': [
58 | ...defaultTheme.fontFamily.serif
59 | ],
60 | 'mono-primary': [
61 | ...defaultTheme.fontFamily.mono
62 | ],
63 | },
64 | boxShadow: theme => ({
65 | 'outline': '0 0 0 3px ' + theme('colors.primary.500') + alpha[20],
66 | 'focus': '0 0 0 3px ' + theme('colors.primary.500') + alpha[20]
67 | }),
68 | container: {
69 | center: true,
70 | padding: {
71 | default: '1rem',
72 | sm: '2rem',
73 | lg: '4rem',
74 | xl: '5rem'
75 | }
76 | },
77 | height: {
78 | 'screen-fix': 'calc(var(--vh, 1vh) * 100);'
79 | },
80 | inset: {
81 | '0': 0,
82 | '1/2': '50%'
83 | },
84 | // Plugins
85 | textStyles: theme => ({
86 | richText: {
87 | fontSize: theme('fontSize.base')[0],
88 | lineHeight: theme('fontSize.base')[1],
89 | 'h1, h2, h3, h4, h5, h6': {
90 | marginBottom: theme('spacing.4')
91 | },
92 | 'h1': {
93 | fontSize: theme('fontSize.3xl')[0],
94 | lineHeight: theme('fontSize.3xl')[1]
95 | },
96 | 'h2': {
97 | fontSize: theme('fontSize.2xl')[0],
98 | lineHeight: theme('fontSize.2xl')[1]
99 | },
100 | 'h3': {
101 | fontSize: theme('fontSize.xl')[0],
102 | lineHeight: theme('fontSize.xl')[1]
103 | },
104 | 'h4': {
105 | fontSize: theme('fontSize.lg')[0],
106 | lineHeight: theme('fontSize.lg')[1]
107 | },
108 | 'h5': {
109 | fontSize: theme('fontSize.md')[0],
110 | lineHeight: theme('fontSize.md')[1]
111 | },
112 | 'h6': {
113 | fontSize: theme('fontSize.base')[0],
114 | lineHeight: theme('fontSize.base')[1]
115 | },
116 | 'ul,ol': {
117 | listStylePosition: 'inside',
118 | marginBottom: theme('spacing.4')
119 | },
120 | 'ul': {
121 | listStyleType: 'disc',
122 | },
123 | 'ol': {
124 | listStyleType: 'decimal',
125 | },
126 | 'a': {
127 | textDecoration: 'underline',
128 | color: theme('colors.primary.500'),
129 | '&:hover': {
130 | color: theme('colors.primary.600')
131 | }
132 | },
133 | 'b, strong': {
134 | fontWeight: theme('fontWeight.bold'),
135 | },
136 | 'i, em': {
137 | fontStyle: 'italic',
138 | }
139 | }
140 | }),
141 | animations: {},
142 | aspectRatio: {
143 | 'square': [1, 1],
144 | '16/9': [16, 9],
145 | '4/3': [4, 3]
146 | }
147 | },
148 | screens: {
149 | ...defaultTheme.screens,
150 | }
151 | },
152 | variants: {
153 | textColor: ['responsive', 'hover', 'focus', 'group-hover'],
154 | backgroundColor: ['responsive', 'hover', 'focus', 'group-hover'],
155 | opacity: ['responsive', 'hover', 'group-hover'],
156 | translate: ['responsive', 'hover', 'group-hover'],
157 | scale: ['responsive', 'hover', 'group-hover'],
158 | animations: ['responsive', 'hover', 'group-hover']
159 | },
160 | plugins: [
161 | require('tailwindcss-typography')({ componentPrefix: '' }),
162 | require('tailwindcss-aspect-ratio')(),
163 | require('tailwindcss-animations')
164 | ],
165 | purge: []
166 | }
167 |
--------------------------------------------------------------------------------
/web/dist/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/madebyshape/tailwind-css/c131d2bc030d70b88e2f8d71bd150634eb82407b/web/dist/images/favicon.png
--------------------------------------------------------------------------------
/web/dist/js/app.js:
--------------------------------------------------------------------------------
1 | !function(e){"use strict";e.loadCSS||(e.loadCSS=function(){});var t=loadCSS.relpreload={};if(t.support=function(){var t;try{t=e.document.createElement("link").relList.supports("preload")}catch(e){t=!1}return function(){return t}}(),t.bindMediaToggle=function(e){var t=e.media||"all";function n(){e.addEventListener?e.removeEventListener("load",n):e.attachEvent&&e.detachEvent("onload",n),e.setAttribute("onload",null),e.media=t}e.addEventListener?e.addEventListener("load",n):e.attachEvent&&e.attachEvent("onload",n),setTimeout(function(){e.rel="stylesheet",e.media="only x"}),setTimeout(n,3e3)},t.poly=function(){if(!t.support())for(var n=e.document.getElementsByTagName("link"),i=0;i{const t=u(e.name),n=t.match(a),i=t.match(/:([a-zA-Z\-:]+)/),r=t.match(/\.[^.\]]+(?=[^\]]*$)/g)||[];return{type:n?n[1]:null,value:i?i[1]:null,modifiers:r.map(e=>e.replace(".","")),expression:e.value}}).filter(e=>!t||e.type===t)}function u(e){return e.startsWith("@")?e.replace("@","x-on:"):e.startsWith(":")?e.replace(":","x-bind:"):e}function d(e,t,n=!1){if(n)return t();const i=c(e,"transition"),r=c(e,"show")[0];if(r&&r.modifiers.includes("transition")){let n=r.modifiers;if(n.includes("out")&&!n.includes("in"))return t();const i=n.includes("in")&&n.includes("out");(function(e,t,n){const i={duration:p(t,"duration",150),origin:p(t,"origin","center"),first:{opacity:0,scale:p(t,"scale",95)},second:{opacity:1,scale:100}};m(e,t,n,()=>{},i)})(e,n=i?n.filter((e,t)=>t["enter","enter-start","enter-end"].includes(e.value)).length>0?function(e,t,n){const i=(t.find(e=>"enter"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),r=(t.find(e=>"enter-start"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),o=(t.find(e=>"enter-end"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e);h(e,i,r,o,n,()=>{})}(e,i,t):t()}function f(e,t,n=!1){if(n)return t();const i=c(e,"transition"),r=c(e,"show")[0];if(r&&r.modifiers.includes("transition")){let n=r.modifiers;if(n.includes("in")&&!n.includes("out"))return t();const i=n.includes("in")&&n.includes("out");(function(e,t,n,i){const r={duration:n?p(t,"duration",150):p(t,"duration",150)/2,origin:p(t,"origin","center"),first:{opacity:1,scale:100},second:{opacity:0,scale:p(t,"scale",95)}};m(e,t,()=>{},i,r)})(e,n=i?n.filter((e,t)=>t>n.indexOf("out")):n,i,t)}else i.filter(e=>["leave","leave-start","leave-end"].includes(e.value)).length>0?function(e,t,n){const i=(t.find(e=>"leave"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),r=(t.find(e=>"leave-start"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e),o=(t.find(e=>"leave-end"===e.value)||{expression:""}).expression.split(" ").filter(e=>""!==e);h(e,i,r,o,()=>{},n)}(e,i,t):t()}function p(e,t,n){if(-1===e.indexOf(t))return n;const i=e[e.indexOf(t)+1];if(!i)return n;if("scale"===t&&!g(i))return n;if("duration"===t){let e=i.match(/([0-9]+)ms/);if(e)return e[1]}return"origin"===t&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[i,e[e.indexOf(t)+2]].join(" "):i}function m(e,t,n,i,r){const o=e.style.opacity,s=e.style.transform,a=e.style.transformOrigin,l=!t.includes("opacity")&&!t.includes("scale"),c=l||t.includes("opacity"),u=l||t.includes("scale"),d={start(){c&&(e.style.opacity=r.first.opacity),u&&(e.style.transform=`scale(${r.first.scale/100})`)},during(){u&&(e.style.transformOrigin=r.origin),e.style.transitionProperty=[c?"opacity":"",u?"transform":""].join(" ").trim(),e.style.transitionDuration=`${r.duration/1e3}s`,e.style.transitionTimingFunction="cubic-bezier(0.4, 0.0, 0.2, 1)"},show(){n()},end(){c&&(e.style.opacity=r.second.opacity),u&&(e.style.transform=`scale(${r.second.scale/100})`)},hide(){i()},cleanup(){c&&(e.style.opacity=o),u&&(e.style.transform=s),u&&(e.style.transformOrigin=a),e.style.transitionProperty=null,e.style.transitionDuration=null,e.style.transitionTimingFunction=null}};v(e,d)}function h(e,t,n,i,r,o){const s=e.__x_original_classes||[],a={start(){e.classList.add(...n)},during(){e.classList.add(...t)},show(){r()},end(){e.classList.remove(...n.filter(e=>!s.includes(e))),e.classList.add(...i)},hide(){o()},cleanup(){e.classList.remove(...t.filter(e=>!s.includes(e))),e.classList.remove(...i.filter(e=>!s.includes(e)))}};v(e,a)}function v(e,t){t.start(),t.during(),requestAnimationFrame(()=>{let n=1e3*Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s",""));t.show(),requestAnimationFrame(()=>{t.end(),setTimeout(()=>{t.hide(),e.isConnected&&t.cleanup()},n)})})}function g(e){return!isNaN(e)}function y(e,t,i,r,o){"template"!==t.tagName.toLowerCase()&&console.warn("Alpine: [x-for] directive should only be added to tags.");let s=function(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,n=e.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!n)return;let i={};i.items=n[2].trim();let r=n[1].trim().replace(/^\(|\)$/g,""),o=r.match(t);o?(i.item=r.replace(t,"").trim(),i.index=o[1].trim(),o[2]&&(i.collection=o[2].trim())):i.item=r;return i}(i),a=function(e,t,n,i){let r=c(t,"if")[0];if(r&&!e.evaluateReturnExpression(t,r.expression))return[];return e.evaluateReturnExpression(t,n.items,i)}(e,t,s,o),l=t;a.forEach((i,u)=>{let f=function(e,t,i,r,o){let s=o?n({},o):{};s[e.item]=t,e.index&&(s[e.index]=i);e.collection&&(s[e.collection]=r);return s}(s,i,u,a,o()),p=function(e,t,n,i){let r=c(t,"bind").filter(e=>"key"===e.value)[0];return r?e.evaluateReturnExpression(t,r.expression,()=>i):n}(e,t,u,f),m=function(e,t){if(!e)return;if(e.__x_for_key===t)return e;let n=e;for(;n;){if(n.__x_for_key===t)return n.parentElement.insertBefore(n,e);n=!(!n.nextElementSibling||void 0===n.nextElementSibling.__x_for_key)&&n.nextElementSibling}}(l.nextElementSibling,p);m?(delete m.__x_for_key,m.__x_for=f,e.updateElements(m,()=>m.__x_for)):(d(m=function(e,t){let n=document.importNode(e.content,!0);1!==n.childElementCount&&console.warn("Alpine: tag with [x-for] encountered with multiple element roots. Make sure only has a single child node.");return t.parentElement.insertBefore(n,t.nextElementSibling),t.nextElementSibling}(t,l),()=>{},r),m.__x_for=f,e.initializeElements(m,()=>m.__x_for)),(l=m).__x_for_key=p}),function(e){var t=!(!e.nextElementSibling||void 0===e.nextElementSibling.__x_for_key)&&e.nextElementSibling;for(;t;){let e=t,n=t.nextElementSibling;f(t,()=>{e.remove()}),t=!(!n||void 0===n.__x_for_key)&&n}}(l)}function b(e,t,n,r,o,s){var a=e.evaluateReturnExpression(t,r,o);if("value"===n)if(void 0===a&&r.match(/\./).length&&(a=""),"radio"===t.type)void 0===t.attributes.value&&"bind"===s?t.value=a:"bind"!==s&&(t.checked=t.value==a);else if("checkbox"===t.type){if(Array.isArray(a)){let e=!1;a.forEach(n=>{n==t.value&&(e=!0)}),t.checked=e}else t.checked=!!a;"string"==typeof a&&(t.value=a)}else if("SELECT"===t.tagName)!function(e,t){const n=[].concat(t).map(e=>e+"");Array.from(e.options).forEach(e=>{e.selected=n.includes(e.value||e.text)})}(t,a);else{if(t.value===a)return;t.value=a}else if("class"===n)if(Array.isArray(a)){const e=t.__x_original_classes||[];t.setAttribute("class",i(e.concat(a)).join(" "))}else if("object"==typeof a){Object.keys(a).sort((e,t)=>a[e]-a[t]).forEach(e=>{a[e]?e.split(" ").filter(Boolean).forEach(e=>t.classList.add(e)):e.split(" ").filter(Boolean).forEach(e=>t.classList.remove(e))})}else{const e=t.__x_original_classes||[],n=a.split(" ").filter(Boolean);t.setAttribute("class",i(e.concat(n)).join(" "))}else[null,void 0,!1].includes(a)?t.removeAttribute(n):!function(e){return["disabled","checked","required","readonly","hidden","open","selected","autofocus","itemscope","multiple","novalidate","allowfullscreen","allowpaymentrequest","formnovalidate","autoplay","controls","loop","muted","playsinline","default","ismap","reversed","async","defer","nomodule"].includes(e)}(n)?t.setAttribute(n,a):t.setAttribute(n,n)}function x(e,t,n,i,r,s={}){if(i.includes("away")){let o=a=>{t.contains(a.target)||t.offsetWidth<1&&t.offsetHeight<1||(w(e,r,a,s),i.includes("once")&&document.removeEventListener(n,o))};document.addEventListener(n,o)}else{let a=i.includes("window")?window:i.includes("document")?document:t,l=o=>{if(a!==window&&a!==document||document.body.contains(t)){if(!(function(e){return["keydown","keyup"].includes(e)}(n)&&function(e,t){let n=t.filter(e=>!["window","document","prevent","stop"].includes(e));if(n.includes("debounce")){let e=n.indexOf("debounce");n.splice(e,g((n[e+1]||"invalid-wait").split("ms")[0])?2:1)}if(0===n.length)return!1;if(1===n.length&&n[0]===E(e.key))return!1;const i=["ctrl","shift","alt","meta","cmd","super"].filter(e=>n.includes(e));if(n=n.filter(e=>!i.includes(e)),i.length>0){const t=i.filter(t=>("cmd"!==t&&"super"!==t||(t="meta"),e[`${t}Key`]));if(t.length===i.length&&n[0]===E(e.key))return!1}return!0}(o,i)||(i.includes("prevent")&&o.preventDefault(),i.includes("stop")&&o.stopPropagation(),i.includes("self")&&o.target!==t))){!1===w(e,r,o,s)?o.preventDefault():i.includes("once")&&a.removeEventListener(n,l)}}else a.removeEventListener(n,l)};if(i.includes("debounce")){let e=i[i.indexOf("debounce")+1]||"invalid-wait",t=g(e.split("ms")[0])?Number(e.split("ms")[0]):250;l=o(l,t)}a.addEventListener(n,l)}}function w(e,t,i,r){return e.evaluateCommandExpression(i.target,t,()=>n({},r(),{$event:i}))}function E(e){switch(e){case"/":return"slash";case" ":case"Spacebar":return"space";default:return e&&e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}}function _(e,t,n){return"radio"===e.type&&(e.hasAttribute("name")||e.setAttribute("name",n)),(n,i)=>{if(n instanceof CustomEvent&&n.detail)return n.detail;if("checkbox"===e.type)return Array.isArray(i)?n.target.checked?i.concat([n.target.value]):i.filter(e=>e!==n.target.value):n.target.checked;if("select"===e.tagName.toLowerCase()&&e.multiple)return t.includes("number")?Array.from(n.target.selectedOptions).map(e=>{const t=e.value||e.text,n=t?parseFloat(t):null;return isNaN(n)?t:n}):Array.from(n.target.selectedOptions).map(e=>e.value||e.text);{const e=n.target.value,i=e?parseFloat(e):null;return t.includes("number")?isNaN(i)?e:i:t.includes("trim")?e.trim():e}}}const{isArray:S}=Array,{getPrototypeOf:k,create:O,defineProperty:C,defineProperties:A,isExtensible:T,getOwnPropertyDescriptor:N,getOwnPropertyNames:$,getOwnPropertySymbols:j,preventExtensions:P,hasOwnProperty:D}=Object,{push:L,concat:z,map:R}=Array.prototype;function F(e){return void 0===e}function M(e){return"function"==typeof e}const B=new WeakMap;function I(e,t){B.set(e,t)}const q=e=>B.get(e)||e;function U(e,t){return e.valueIsObservable(t)?e.getProxy(t):t}function W(e,t,n){z.call($(n),j(n)).forEach(i=>{let r=N(n,i);r.configurable||(r=ee(e,r,U)),C(t,i,r)}),P(t)}class H{constructor(e,t){this.originalTarget=t,this.membrane=e}get(e,t){const{originalTarget:n,membrane:i}=this,r=n[t],{valueObserved:o}=i;return o(n,t),i.getProxy(r)}set(e,t,n){const{originalTarget:i,membrane:{valueMutated:r}}=this;return i[t]!==n?(i[t]=n,r(i,t)):"length"===t&&S(i)&&r(i,t),!0}deleteProperty(e,t){const{originalTarget:n,membrane:{valueMutated:i}}=this;return delete n[t],i(n,t),!0}apply(e,t,n){}construct(e,t,n){}has(e,t){const{originalTarget:n,membrane:{valueObserved:i}}=this;return i(n,t),t in n}ownKeys(e){const{originalTarget:t}=this;return z.call($(t),j(t))}isExtensible(e){const t=T(e);if(!t)return t;const{originalTarget:n,membrane:i}=this,r=T(n);return r||W(i,e,n),r}setPrototypeOf(e,t){}getPrototypeOf(e){const{originalTarget:t}=this;return k(t)}getOwnPropertyDescriptor(e,t){const{originalTarget:n,membrane:i}=this,{valueObserved:r}=this.membrane;r(n,t);let o=N(n,t);if(F(o))return o;const s=N(e,t);return F(s)?((o=ee(i,o,U)).configurable||C(e,t,o),o):s}preventExtensions(e){const{originalTarget:t,membrane:n}=this;return W(n,e,t),P(t),!0}defineProperty(e,t,n){const{originalTarget:i,membrane:r}=this,{valueMutated:o}=r,{configurable:s}=n;if(D.call(n,"writable")&&!D.call(n,"value")){const e=N(i,t);n.value=e.value}return C(i,t,function(e){return D.call(e,"value")&&(e.value=q(e.value)),e}(n)),!1===s&&C(e,t,ee(r,n,U)),o(i,t),!0}}function V(e,t){return e.valueIsObservable(t)?e.getReadOnlyProxy(t):t}class K{constructor(e,t){this.originalTarget=t,this.membrane=e}get(e,t){const{membrane:n,originalTarget:i}=this,r=i[t],{valueObserved:o}=n;return o(i,t),n.getReadOnlyProxy(r)}set(e,t,n){return!1}deleteProperty(e,t){return!1}apply(e,t,n){}construct(e,t,n){}has(e,t){const{originalTarget:n,membrane:{valueObserved:i}}=this;return i(n,t),t in n}ownKeys(e){const{originalTarget:t}=this;return z.call($(t),j(t))}setPrototypeOf(e,t){}getOwnPropertyDescriptor(e,t){const{originalTarget:n,membrane:i}=this,{valueObserved:r}=i;r(n,t);let o=N(n,t);if(F(o))return o;const s=N(e,t);return F(s)?(o=ee(i,o,V),D.call(o,"set")&&(o.set=void 0),o.configurable||C(e,t,o),o):s}preventExtensions(e){return!1}defineProperty(e,t,n){return!1}}function Z(e){let t=void 0;return S(e)?t=[]:"object"==typeof e&&(t={}),t}const G=Object.prototype;function J(e){if(null===e)return!1;if("object"!=typeof e)return!1;if(S(e))return!0;const t=k(e);return t===G||null===t||null===k(t)}const Q=(e,t)=>{},X=(e,t)=>{},Y=e=>e;function ee(e,t,n){const{set:i,get:r}=t;return D.call(t,"value")?t.value=n(e,t.value):(F(r)||(t.get=function(){return n(e,r.call(q(this)))}),F(i)||(t.set=function(t){i.call(q(this),e.unwrapProxy(t))})),t}class te{constructor(e){if(this.valueDistortion=Y,this.valueMutated=X,this.valueObserved=Q,this.valueIsObservable=J,this.objectGraph=new WeakMap,!F(e)){const{valueDistortion:t,valueMutated:n,valueObserved:i,valueIsObservable:r}=e;this.valueDistortion=M(t)?t:Y,this.valueMutated=M(n)?n:X,this.valueObserved=M(i)?i:Q,this.valueIsObservable=M(r)?r:J}}getProxy(e){const t=q(e),n=this.valueDistortion(t);if(this.valueIsObservable(n)){const i=this.getReactiveState(t,n);return i.readOnly===e?e:i.reactive}return n}getReadOnlyProxy(e){e=q(e);const t=this.valueDistortion(e);return this.valueIsObservable(t)?this.getReactiveState(e,t).readOnly:t}unwrapProxy(e){return q(e)}getReactiveState(e,t){const{objectGraph:n}=this;let i=n.get(t);if(i)return i;const r=this;return i={get reactive(){const n=new H(r,t),i=new Proxy(Z(t),n);return I(i,e),C(this,"reactive",{value:i}),i},get readOnly(){const n=new K(r,t),i=new Proxy(Z(t),n);return I(i,e),C(this,"readOnly",{value:i}),i}},n.set(t,i),i}}class ne{constructor(e,t=null){this.$el=e;const n=this.$el.getAttribute("x-data"),i=""===n?"{}":n,r=this.$el.getAttribute("x-init");this.unobservedData=t||s(i,{});let{membrane:o,data:a}=this.wrapDataInObservable(this.unobservedData);var l;this.$data=a,this.membrane=o,this.unobservedData.$el=this.$el,this.unobservedData.$refs=this.getRefsProxy(),this.nextTickStack=[],this.unobservedData.$nextTick=(e=>{this.nextTickStack.push(e)}),this.watchers={},this.unobservedData.$watch=((e,t)=>{this.watchers[e]||(this.watchers[e]=[]),this.watchers[e].push(t)}),this.showDirectiveStack=[],this.showDirectiveLastElement,r&&!t&&(this.pauseReactivity=!0,l=this.evaluateReturnExpression(this.$el,r),this.pauseReactivity=!1),this.initializeElements(this.$el),this.listenForNewElementsToInitialize(),"function"==typeof l&&l.call(this.$data)}getUnobservedData(){return function(e,t){let n=e.unwrapProxy(t),i={};return Object.keys(n).forEach(e=>{["$el","$refs","$nextTick","$watch"].includes(e)||(i[e]=n[e])}),i}(this.membrane,this.$data)}wrapDataInObservable(e){var t=this;let n=o(function(){t.updateElements(t.$el)},0);return function(e,t){let n=new te({valueMutated(e,n){t(e,n)}});return{data:n.getProxy(e),membrane:n}}(e,(e,i)=>{t.watchers[i]?t.watchers[i].forEach(t=>t(e[i])):Object.keys(t.watchers).filter(e=>e.includes(".")).forEach(n=>{let r=n.split(".");i===r[r.length-1]&&r.reduce((r,o)=>(Object.is(e,r)&&t.watchers[n].forEach(t=>t(e[i])),r[o]),t.getUnobservedData())}),t.pauseReactivity||n()})}walkAndSkipNestedComponents(e,t,n=(()=>{})){!function e(t,n){if(!1===n(t))return;let i=t.firstElementChild;for(;i;)e(i,n),i=i.nextElementSibling}(e,e=>e.hasAttribute("x-data")&&!e.isSameNode(this.$el)?(e.__x||n(e),!1):t(e))}initializeElements(e,t=(()=>{})){this.walkAndSkipNestedComponents(e,e=>void 0===e.__x_for_key&&(void 0===e.__x_inserted_me&&void this.initializeElement(e,t)),e=>{e.__x=new ne(e)}),this.executeAndClearRemainingShowDirectiveStack(),this.executeAndClearNextTickStack(e)}initializeElement(e,t){e.hasAttribute("class")&&c(e).length>0&&(e.__x_original_classes=e.getAttribute("class").split(" ")),this.registerListeners(e,t),this.resolveBoundAttributes(e,!0,t)}updateElements(e,t=(()=>{})){this.walkAndSkipNestedComponents(e,e=>{if(void 0!==e.__x_for_key&&!e.isSameNode(this.$el))return!1;this.updateElement(e,t)},e=>{e.__x=new ne(e)}),this.executeAndClearRemainingShowDirectiveStack(),this.executeAndClearNextTickStack(e)}executeAndClearNextTickStack(e){if(e===this.$el)for(;this.nextTickStack.length>0;)this.nextTickStack.shift()()}executeAndClearRemainingShowDirectiveStack(){this.showDirectiveStack.reverse().map(e=>new Promise(t=>{e(e=>{t(e)})})).reduce((e,t)=>e.then(()=>t.then(e=>e())),Promise.resolve(()=>{})),this.showDirectiveStack=[],this.showDirectiveLastElement=void 0}updateElement(e,t){this.resolveBoundAttributes(e,!1,t)}registerListeners(e,t){c(e).forEach(({type:i,value:r,modifiers:o,expression:s})=>{switch(i){case"on":x(this,e,r,o,s,t);break;case"model":!function(e,t,i,r,o){var s="select"===t.tagName.toLowerCase()||["checkbox","radio"].includes(t.type)||i.includes("lazy")?"change":"input";x(e,t,s,i,`${r} = rightSideOfExpression($event, ${r})`,()=>n({},o(),{rightSideOfExpression:_(t,i,r)}))}(this,e,o,s,t)}})}resolveBoundAttributes(e,t=!1,n){let i=c(e);if(void 0!==e.type&&"radio"===e.type){const e=i.findIndex(e=>"model"===e.type);e>-1&&i.push(i.splice(e,1)[0])}i.forEach(({type:r,value:o,modifiers:s,expression:a})=>{switch(r){case"model":b(this,e,"value",a,n,r);break;case"bind":if("template"===e.tagName.toLowerCase()&&"key"===o)return;b(this,e,o,a,n,r);break;case"text":var l=this.evaluateReturnExpression(e,a,n);!function(e,t,n){void 0===t&&n.match(/\./).length&&(t=""),e.innerText=t}(e,l,a);break;case"html":!function(e,t,n,i){t.innerHTML=e.evaluateReturnExpression(t,n,i)}(this,e,a,n);break;case"show":l=this.evaluateReturnExpression(e,a,n);!function(e,t,n,i,r=!1){const o=()=>{t.style.display="none"},s=()=>{1===t.style.length&&"none"===t.style.display?t.removeAttribute("style"):t.style.removeProperty("display")};if(!0===r)return void(n?s():o());const a=e=>{n?(""!==t.style.display&&d(t,()=>{s()}),e(()=>{})):"none"!==t.style.display?f(t,()=>{e(()=>{o()})}):e(()=>{})};i.includes("immediate")?a(e=>e()):(e.showDirectiveLastElement&&!e.showDirectiveLastElement.contains(t)&&e.executeAndClearRemainingShowDirectiveStack(),e.showDirectiveStack.push(a),e.showDirectiveLastElement=t)}(this,e,l,s,t);break;case"if":if(i.filter(e=>"for"===e.type).length>0)return;l=this.evaluateReturnExpression(e,a,n);!function(e,t,n,i,r){"template"!==t.nodeName.toLowerCase()&&console.warn("Alpine: [x-if] directive should only be added to tags. See https://github.com/alpinejs/alpine#x-if");const o=t.nextElementSibling&&!0===t.nextElementSibling.__x_inserted_me;if(n&&!o){const n=document.importNode(t.content,!0);t.parentElement.insertBefore(n,t.nextElementSibling),d(t.nextElementSibling,()=>{},i),e.initializeElements(t.nextElementSibling,r),t.nextElementSibling.__x_inserted_me=!0}else!n&&o&&f(t.nextElementSibling,()=>{t.nextElementSibling.remove()},i)}(this,e,l,t,n);break;case"for":y(this,e,a,t,n);break;case"cloak":e.removeAttribute("x-cloak")}})}evaluateReturnExpression(e,t,i=(()=>{})){return s(t,this.$data,n({},i(),{$dispatch:this.getDispatchFunction(e)}))}evaluateCommandExpression(e,t,i=(()=>{})){return function(e,t,n={}){if(Object.keys(t).includes(e)){let i=new Function(["dataContext",...Object.keys(n)],`with(dataContext) { return ${e} }`)(t,...Object.values(n));if("function"==typeof i)return i.call(t,n.$event)}return new Function(["dataContext",...Object.keys(n)],`with(dataContext) { ${e} }`)(t,...Object.values(n))}(t,this.$data,n({},i(),{$dispatch:this.getDispatchFunction(e)}))}getDispatchFunction(e){return(t,n={})=>{e.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0}))}}listenForNewElementsToInitialize(){const e=this.$el;new MutationObserver(e=>{for(let t=0;t{this.$data[e]!==n[e]&&(this.$data[e]=n[e])})}e[t].addedNodes.length>0&&e[t].addedNodes.forEach(e=>{1!==e.nodeType||e.__x_inserted_me||(e.matches("[x-data]")?e.__x=new ne(e):this.initializeElements(e))})}}}).observe(e,{childList:!0,attributes:!0,subtree:!0})}getRefsProxy(){var e=this;return new Proxy({},{get(t,n){return"$isAlpineProxy"===n||(e.walkAndSkipNestedComponents(e.$el,e=>{e.hasAttribute("x-ref")&&e.getAttribute("x-ref")===n&&(i=e)}),i);var i}})}}const ie={version:"2.3.5",start:async function(){r()||await new Promise(e=>{"loading"==document.readyState?document.addEventListener("DOMContentLoaded",e):e()}),this.discoverComponents(e=>{this.initializeComponent(e)}),document.addEventListener("turbolinks:load",()=>{this.discoverUninitializedComponents(e=>{this.initializeComponent(e)})}),this.listenForNewUninitializedComponentsAtRunTime(e=>{this.initializeComponent(e)})},discoverComponents:function(e){document.querySelectorAll("[x-data]").forEach(t=>{e(t)})},discoverUninitializedComponents:function(e,t=null){const n=(t||document).querySelectorAll("[x-data]");Array.from(n).filter(e=>void 0===e.__x).forEach(t=>{e(t)})},listenForNewUninitializedComponentsAtRunTime:function(e){const t=document.querySelector("body");new MutationObserver(e=>{for(let t=0;t0&&e[t].addedNodes.forEach(e=>{1===e.nodeType&&(e.parentElement&&e.parentElement.closest("[x-data]")||this.discoverUninitializedComponents(e=>{this.initializeComponent(e)},e.parentElement))})}).observe(t,{childList:!0,attributes:!0,subtree:!0})},initializeComponent:function(e){e.__x||(e.__x=new ne(e))},clone:function(e,t){t.__x||(t.__x=new ne(t,e.getUnobservedData()))}};return r()||(window.Alpine=ie,window.deferLoadingAlpine?window.deferLoadingAlpine(function(){window.Alpine.start()}):window.Alpine.start()),ie}),function(e,t,n,i){var r=[],o={_version:"3.11.0",_config:{classPrefix:"",enableClasses:!0,enableJSClass:!0,usePrefixes:!0},_q:[],on:function(e,t){var n=this;setTimeout(function(){t(n[e])},0)},addTest:function(e,t,n){r.push({name:e,fn:t,options:n})},addAsyncTest:function(e){r.push({name:null,fn:e})}},s=function(){};s.prototype=o,s=new s;var a=[];function l(e,t){return typeof e===t}var c,u,d=n.documentElement,f="svg"===d.nodeName.toLowerCase();function p(e){var t=d.className,n=s._config.classPrefix||"";if(f&&(t=t.baseVal),s._config.enableJSClass){var i=new RegExp("(^|\\s)"+n+"no-js(\\s|$)");t=t.replace(i,"$1"+n+"js$2")}s._config.enableClasses&&(e.length>0&&(t+=" "+n+e.join(" "+n)),f?d.className.baseVal=t:d.className=t)}function m(e,t){if("object"==typeof e)for(var n in e)c(e,n)&&m(n,e[n]);else{var i=(e=e.toLowerCase()).split("."),r=s[i[0]];if(2===i.length&&(r=r[i[1]]),void 0!==r)return s;t="function"==typeof t?t():t,1===i.length?s[i[0]]=t:(!s[i[0]]||s[i[0]]instanceof Boolean||(s[i[0]]=new Boolean(s[i[0]])),s[i[0]][i[1]]=t),p([(t&&!1!==t?"":"no-")+i.join("-")]),s._trigger(e,t)}return s}function h(){return"function"!=typeof n.createElement?n.createElement(arguments[0]):f?n.createElementNS.call(n,"http://www.w3.org/2000/svg",arguments[0]):n.createElement.apply(n,arguments)}c=l(u={}.hasOwnProperty,"undefined")||l(u.call,"undefined")?function(e,t){return t in e&&l(e.constructor.prototype[t],"undefined")}:function(e,t){return u.call(e,t)},o._l={},o.on=function(e,t){this._l[e]||(this._l[e]=[]),this._l[e].push(t),s.hasOwnProperty(e)&&setTimeout(function(){s._trigger(e,s[e])},0)},o._trigger=function(e,t){if(this._l[e]){var n=this._l[e];setTimeout(function(){var e;for(e=0;e",i.insertBefore(n.lastChild,i.firstChild)}function d(){var e=h.elements;return"string"==typeof e?e.split(" "):e}function f(e){var t=c[e[a]];return t||(t={},l++,e[a]=l,c[l]=t),t}function p(e,n,r){return n||(n=t),i?n.createElement(e):(r||(r=f(n)),!(a=r.cache[e]?r.cache[e].cloneNode():s.test(e)?(r.cache[e]=r.createElem(e)).cloneNode():r.createElem(e)).canHaveChildren||o.test(e)||a.tagUrn?a:r.frag.appendChild(a));var a}function m(e){e||(e=t);var r=f(e);return!h.shivCSS||n||r.hasCSS||(r.hasCSS=!!u(e,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),i||function(e,t){t.cache||(t.cache={},t.createElem=e.createElement,t.createFrag=e.createDocumentFragment,t.frag=t.createFrag()),e.createElement=function(n){return h.shivMethods?p(n,e,t):t.createElem(n)},e.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(e){return t.createElem(e),t.frag.createElement(e),'c("'+e+'")'})+");return n}")(h,t.frag)}(e,r),e}!function(){try{var e=t.createElement("a");e.innerHTML="",n="hidden"in e,i=1==e.childNodes.length||function(){t.createElement("a");var e=t.createDocumentFragment();return void 0===e.cloneNode||void 0===e.createDocumentFragment||void 0===e.createElement}()}catch(e){n=!0,i=!0}}();var h={elements:r.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:"3.7.3",shivCSS:!1!==r.shivCSS,supportsUnknownElements:i,shivMethods:!1!==r.shivMethods,type:"default",shivDocument:m,createElement:p,createDocumentFragment:function(e,n){if(e||(e=t),i)return e.createDocumentFragment();for(var r=(n=n||f(e)).frag.cloneNode(),o=0,s=d(),a=s.length;o+~])("+d().join("|")+")(?=[[\\s,>+~#.:]|$)","gi"),o="$1"+y+"\\:$2";i--;)(t=n[i]=n[i].split("}"))[t.length-1]=t[t.length-1].replace(r,o),n[i]=t.join("}");return n.join("{")}(l.reverse().join("")),n=function(e){for(var t,n=e.getElementsByTagName("*"),i=n.length,r=RegExp("^(?:"+d().join("|")+")$","i"),o=[];i--;)t=n[i],r.test(t.nodeName)&&o.push(t.applyElement(x(t)));return o}(e),t=u(e,l)}),o.attachEvent("onafterprint",function(){!function(e){for(var t=e.length;t--;)e[t].removeNode()}(n),clearTimeout(i._removeSheetTimer),i._removeSheetTimer=setTimeout(s,500)}),e.printShived=!0,e}h.type+=" print",h.shivPrint=w,w(t),"object"==typeof module&&module.exports&&(module.exports=h)}(void 0!==t?t:this,n);var v={elem:h("modernizr")};s._q.push(function(){delete v.elem});var g={style:v.elem.style};function y(e,t,i,r){var o,s,a,l,c="modernizr",u=h("div"),p=function(){var e=n.body;return e||((e=h(f?"svg":"body")).fake=!0),e}();if(parseInt(i,10))for(;i--;)(a=h("div")).id=r?r[i]:c+(i+1),u.appendChild(a);return(o=h("style")).type="text/css",o.id="s"+c,(p.fake?p:u).appendChild(o),p.appendChild(u),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(n.createTextNode(e)),u.id=c,p.fake&&(p.style.background="",p.style.overflow="hidden",l=d.style.overflow,d.style.overflow="hidden",d.appendChild(p)),s=t(u,e),p.fake?(p.parentNode.removeChild(p),d.style.overflow=l,d.offsetHeight):u.parentNode.removeChild(u),!!s}function b(e){return e.replace(/([A-Z])/g,function(e,t){return"-"+t.toLowerCase()}).replace(/^ms-/,"-ms-")}function x(e,n){var r=e.length;if("CSS"in t&&"supports"in t.CSS){for(;r--;)if(t.CSS.supports(b(e[r]),n))return!0;return!1}if("CSSSupportsRule"in t){for(var o=[];r--;)o.push("("+b(e[r])+":"+n+")");return y("@supports ("+(o=o.join(" or "))+") { #modernizr { position: absolute; } }",function(e){return"absolute"===function(e,n,i){var r;if("getComputedStyle"in t){r=getComputedStyle.call(t,e,n);var o=t.console;null!==r?i&&(r=r.getPropertyValue(i)):o&&o[o.error?"error":"log"].call(o,"getComputedStyle returning null, its possible modernizr test results are inaccurate")}else r=!n&&e.currentStyle&&e.currentStyle[i];return r}(e,null,"position")})}return i}s._q.unshift(function(){delete g.style});o.testProp=function(e,t,n){return function(e,t,n,r){if(r=!l(r,"undefined")&&r,!l(n,"undefined")){var o=x(e,n);if(!l(o,"undefined"))return o}for(var s,a,c,u,d,f=["modernizr","tspan","samp"];!g.style&&f.length;)s=!0,g.modElem=h(f.shift()),g.style=g.modElem.style;function p(){s&&(delete g.style,delete g.modElem)}for(c=e.length,a=0;a
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Tailwind CSS
11 |
12 |
13 |
14 |
17 |
18 |
19 |
20 |
23 |
24 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------