├── .DS_Store ├── .eslintrc.json ├── .gitignore ├── README.md ├── dist ├── css │ ├── stuff.css │ ├── stuff.css.map │ ├── stuff.min.css │ ├── stuff.min.css.map │ └── themes │ │ ├── theme.css │ │ ├── theme.css.map │ │ ├── theme.min.css │ │ └── theme.min.css.map └── js │ ├── aside.js │ ├── src │ ├── color-picker.js │ ├── copy.js │ ├── custom-darkmode.js │ ├── darkmode.js │ ├── flex.js │ ├── material-design-colors.js │ └── toggle-navigation.js │ ├── stuff.js │ ├── stuff.min.js │ ├── stuffcustomization.js │ ├── stuffcustomization.min.js │ ├── stuffgrid.js │ ├── stuffgrid.min.js │ ├── stuffmodal.js │ └── stuffmodal.min.js ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── next.svg ├── thirteen.svg └── vercel.svg ├── scss ├── common │ ├── _class.scss │ ├── _fluid.scss │ ├── _functions.scss │ ├── _responsive.scss │ ├── _slim.scss │ ├── _spacing.scss │ └── _variables.scss ├── components │ ├── _accordion.scss │ ├── _breadcrumb.scss │ ├── _card.scss │ ├── _dropdown.scss │ ├── _modal.scss │ ├── _nav.scss │ └── _progress.scss ├── content │ ├── _button.scss │ ├── _code.scss │ ├── _embedded.scss │ ├── _form-alt-input-types.scss │ ├── _form-checkbox-radio.scss │ ├── _form.scss │ ├── _images.scss │ ├── _miscs.scss │ ├── _table.scss │ └── _typography.scss ├── layout │ ├── _container.scss │ ├── _document.scss │ ├── _flex.scss │ ├── _grid.scss │ ├── _scroller.scss │ ├── _section.scss │ └── _sectioning.scss ├── postcss.config.js ├── stuff.scss ├── themes │ ├── default │ │ ├── _colors.scss │ │ ├── _dark.scss │ │ ├── _light.scss │ │ └── _styles.scss │ └── theme.scss └── utilities │ ├── _accessibility.scss │ ├── _loading.scss │ ├── _reduce-motion.scss │ └── _tooltip.scss ├── src ├── components │ ├── canonicalUrl.tsx │ ├── darkmode.tsx │ ├── footer.tsx │ ├── hero.tsx │ ├── layout.tsx │ ├── navbar.tsx │ ├── sidebar.tsx │ └── toogleNav.js ├── pages │ ├── HomePage.tsx │ ├── _app.tsx │ ├── _document.tsx │ ├── api │ │ └── hello.ts │ ├── docs │ │ ├── components │ │ │ ├── accordion.tsx │ │ │ ├── breadcrumb.tsx │ │ │ ├── buttons.tsx │ │ │ ├── cards.tsx │ │ │ └── navbar.tsx │ │ ├── contents │ │ │ └── typography.tsx │ │ ├── customize │ │ │ ├── css-variables.tsx │ │ │ └── themes.tsx │ │ ├── download.tsx │ │ ├── index.tsx │ │ └── layout │ │ │ ├── containers.tsx │ │ │ ├── flex.tsx │ │ │ └── grid.tsx │ ├── examples │ │ ├── accordion.tsx │ │ ├── button.tsx │ │ ├── card.tsx │ │ ├── container.tsx │ │ ├── dropdown.tsx │ │ ├── flex.tsx │ │ ├── grid.tsx │ │ ├── index.tsx │ │ ├── themes.tsx │ │ └── typography.tsx │ └── index.tsx └── static │ ├── css │ ├── stuff.docs.css │ ├── stuff.docs.css.map │ ├── stuff.docs.min.css │ └── stuff.docs.min.css.map │ ├── img │ ├── 2.svg │ ├── header.svg │ ├── logo.psd │ ├── meta-img.jpg │ ├── p.png │ └── stuff-transparent.png │ └── scss │ ├── components │ ├── _modal.scss │ └── _nav.scss │ ├── content │ ├── _code.scss │ └── _typography.scss │ ├── layout │ ├── _aside.scss │ ├── _document.scss │ ├── _documentation.scss │ └── _main.scss │ ├── stuff.docs.scss │ └── themes │ ├── _docs.scss │ └── docs │ ├── _dark.scss │ ├── _icons.scss │ └── _light.scss ├── tsconfig.json └── yarn.lock /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fajarspace/Stuff-CSS/4301b51f35190c7479698b0eb28dfd92068b970b/.DS_Store -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "react/no-unescaped-entities": 0, 5 | "@next/next/no-img-element": "off", 6 | "@next/next/no-html-link-for-pages": "off" 7 | // "jsx-a11y/anchor-is-valid": "off" 8 | } 9 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | -------------------------------------------------------------------------------- /dist/js/src/color-picker.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Color Picker 3 | */ 4 | 5 | export const colorPicker = { 6 | 7 | // Config 8 | colors: null, 9 | buttonsTarget: '#customization article[data-theme="generated"]', 10 | selectorButton: '#customization button[data-color]', 11 | selectorSection: '#customization', 12 | buttons: null, 13 | generatedStyles: null, 14 | 15 | // Init 16 | init() { 17 | this.generateButtons(); 18 | this.setActiveButton('pink'); 19 | this.generateTheme('pink'); 20 | }, 21 | 22 | // Generate Buttons 23 | generateButtons() { 24 | // Init 25 | let innerButtons = ''; 26 | let innerStyles = ''; 27 | 28 | // Loop colors 29 | for (const color in this.colors) { 30 | // Buttons 31 | innerButtons += ``; 32 | 33 | // Styles 34 | innerStyles += ` 35 | button[data-color="${color}"] { 36 | background-color: ${this.colors[color]['600']}; 37 | } 38 | [data-theme="light"] button[data-color="${color}"]:hover, 39 | [data-theme="light"] button[data-color="${color}"]:active, 40 | [data-theme="light"] button[data-color="${color}"]:focus { 41 | background-color: ${this.colors[color]['700']}; ' 42 | } 43 | [data-theme="dark"] button[data-color="${color}"]:hover, 44 | [data-theme="dark"] button[data-color="${color}"]:active, 45 | [data-theme="dark"] button[data-color="${color}"]:focus { 46 | background-color: ${this.colors[color]['500']}; 47 | }`; 48 | } 49 | 50 | // Insert buttons 51 | let containerButtons = document.createElement('FIGURE'); 52 | containerButtons.innerHTML = innerButtons; 53 | document.querySelector(this.buttonsTarget).before(containerButtons); 54 | 55 | // Buttons listeners 56 | this.buttons = document.querySelectorAll(this.selectorButton); 57 | this.buttons.forEach(button => { 58 | button.addEventListener('click', event => { 59 | let color = event.target.getAttribute('data-color'); 60 | this.setActiveButton(color); 61 | this.generateTheme(color); 62 | }, false); 63 | }); 64 | 65 | // Insert CSS Styles 66 | let containerStyles = document.createElement('STYLE'); 67 | containerStyles.setAttribute('title', 'color-picker'); 68 | this.generatedStyles = this.minifyCSS(innerStyles); 69 | containerStyles.innerHTML = this.generatedStyles; 70 | document.querySelector('head').appendChild(containerStyles); 71 | }, 72 | 73 | // Set active button 74 | setActiveButton(color) { 75 | // Remove all active states 76 | this.buttons.forEach(button => { 77 | button.removeAttribute('class'); 78 | }); 79 | 80 | // Set active state 81 | let buttonPicked = document.querySelector(this.selectorButton + '[data-color="' + color + '"]'); 82 | buttonPicked.setAttribute('class', 'picked'); 83 | }, 84 | 85 | // Set active button 86 | generateTheme(color) { 87 | let name = color; 88 | let data = this.colors[color]; 89 | 90 | // 1. Update name and colors in demo code 91 | let swaps = { 92 | '.name': name.charAt(0).toUpperCase() + name.substring(1) + ' ', 93 | '.c500': data[500], 94 | '.c600': data[600], 95 | '.c700': data[700], 96 | '.c600-outline-light': this.hexToRgbA(data[600], 0.125), 97 | '.c600-outline-dark': this.hexToRgbA(data[600], 0.25), 98 | '.inverse': data['inverse'], 99 | }; 100 | 101 | Object.keys(swaps).forEach(swap => { 102 | let targets = document.querySelectorAll(this.selectorSection + ' ' + swap); 103 | targets.forEach(target => { 104 | target.innerHTML = swaps[swap]; 105 | }); 106 | }); 107 | 108 | // 2. Update CSS Styles 109 | const innerStyles = ` 110 | [data-theme="generated"] { 111 | --h4-color: ${data[700]}; 112 | --primary: ${data[600]}; 113 | --primary-hover: ${data[700]}; 114 | --primary-focus: ${this.hexToRgbA(data[600], 0.125)}; 115 | --primary-inverse: ${data['inverse']}; 116 | } 117 | @media only screen and (prefers-color-scheme: dark) { 118 | :root:not([data-theme="light"]) [data-theme="generated"] { 119 | --h4-color: ${data[400]}; 120 | --primary: ${data[600]}; 121 | --primary-hover: ${data[500]}; 122 | --primary-focus: ${this.hexToRgbA(data[600], 0.25)}; 123 | --primary-inverse: ${data['inverse']}; 124 | } 125 | } 126 | [data-theme="dark"] [data-theme="generated"] { 127 | --h4-color: ${data[500]}; 128 | --primary: ${data[600]}; 129 | --primary-hover: ${data[500]}; 130 | --primary-focus: ${this.hexToRgbA(data[600], 0.25)}; 131 | --primary-inverse: ${data['inverse']}; 132 | } 133 | [data-theme="generated"] { 134 | --form-element-active-border-color: var(--primary); 135 | --form-element-focus-color: var(--primary-focus); 136 | --switch-color: var(--primary-inverse); 137 | --switch-checked-background-color: var(--primary); 138 | }`; 139 | 140 | document.querySelector('style[title="color-picker"]').innerHTML = 141 | this.generatedStyles + this.minifyCSS(innerStyles); 142 | }, 143 | 144 | // Minify CSS 145 | minifyCSS(css) { 146 | return css.replace(/^ +/gm, ''); 147 | }, 148 | 149 | // Hexadecimal to Rgba 150 | hexToRgbA(hex, alpha) { 151 | let c; 152 | if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) { 153 | c = hex.substring(1).split(''); 154 | if (c.length == 3) { 155 | c = [c[0], c[0], c[1], c[1], c[2], c[2]]; 156 | } 157 | c = '0x' + c.join(''); 158 | return ( 159 | 'rgba(' + 160 | [(c >> 16) & 255, (c >> 8) & 255, c & 255].join(', ') + 161 | ', ' + 162 | alpha + 163 | ')' 164 | ); 165 | } 166 | throw new Error('Bad Hex'); 167 | }, 168 | }; 169 | 170 | export default colorPicker; 171 | -------------------------------------------------------------------------------- /dist/js/src/copy.js: -------------------------------------------------------------------------------- 1 | export const copyButtonLabel = "📋"; 2 | 3 | // use a class selector if available 4 | let blocks = document.querySelectorAll("pre"); 5 | 6 | blocks.forEach((block) => { 7 | // only add button if browser supports Clipboard API 8 | if (navigator.clipboard) { 9 | let button = document.createElement("div"); 10 | 11 | button.innerText = copyButtonLabel; 12 | block.appendChild(button); 13 | 14 | button.addEventListener("click", async () => { 15 | await copyCode(block, button); 16 | }); 17 | } 18 | }); 19 | 20 | async function copyCode(block, button) { 21 | let code = block.querySelector("code"); 22 | let text = code.innerText; 23 | 24 | await navigator.clipboard.writeText(text); 25 | 26 | // visual feedback that task is completed 27 | button.innerText = "Code Copied"; 28 | 29 | setTimeout(() => { 30 | button.innerText = copyButtonLabel; 31 | }, 700); 32 | } 33 | export default copyButtonLabel; -------------------------------------------------------------------------------- /dist/js/src/custom-darkmode.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export const customDarkmode = { 4 | 5 | // Config 6 | _scheme: 'auto', 7 | change: { 8 | light: '', 9 | dark: '', 10 | }, 11 | buttonsTarget: '.customdarkmode', 12 | localStorageKey: 'stuffPreferedColorScheme', 13 | 14 | // Init 15 | init() { 16 | this.scheme = this.schemeFromLocalStorage; 17 | this.initSwitchers(); 18 | }, 19 | 20 | // Get color scheme from local storage 21 | get schemeFromLocalStorage() { 22 | if (typeof window.localStorage !== 'undefined') { 23 | if (window.localStorage.getItem(this.localStorageKey) !== null) { 24 | return window.localStorage.getItem(this.localStorageKey); 25 | } 26 | } 27 | return this._scheme; 28 | }, 29 | 30 | // Prefered color scheme 31 | get preferedColorScheme() { 32 | return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; 33 | }, 34 | 35 | // Init switchers 36 | initSwitchers() { 37 | const buttons = document.querySelectorAll(this.buttonsTarget); 38 | buttons.forEach(button => { 39 | button.addEventListener('click', () => { 40 | this.scheme == 'dark' ? this.scheme = 'light' : this.scheme = 'dark'; 41 | }, false); 42 | }); 43 | }, 44 | 45 | // Add new button 46 | addButton(config) { 47 | let button = document.createElement(config.tag); 48 | button.className = config.class; 49 | document.querySelector(config.target).appendChild(button); 50 | }, 51 | 52 | // Set scheme 53 | set scheme(scheme) { 54 | if (scheme == 'auto') { 55 | this.preferedColorScheme == 'light' ? this._scheme = 'light' : this._scheme = 'dark'; 56 | } 57 | else if (scheme == 'dark' || scheme == 'light') { 58 | this._scheme = scheme; 59 | } 60 | this.applyScheme(); 61 | this.schemeToLocalStorage(); 62 | }, 63 | 64 | // Get scheme 65 | get scheme() { 66 | return this._scheme; 67 | }, 68 | 69 | // Apply scheme 70 | applyScheme() { 71 | document.querySelector('html').setAttribute('data-theme', this.scheme); 72 | const buttons = document.querySelectorAll(this.buttonsTarget); 73 | buttons.forEach( 74 | button => { 75 | const text = this.scheme == 'dark' ? this.change.dark : this.change.light; 76 | button.innerHTML = text; 77 | button.setAttribute('aria-label', text.replace(/<[^>]*>?/gm, '')); 78 | } 79 | ); 80 | }, 81 | 82 | // Store scheme to local storage 83 | schemeToLocalStorage() { 84 | if (typeof window.localStorage !== 'undefined') { 85 | window.localStorage.setItem(this.localStorageKey, this.scheme); 86 | } 87 | }, 88 | }; 89 | 90 | export default customDarkmode; 91 | -------------------------------------------------------------------------------- /dist/js/src/darkmode.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export const darkMode = { 4 | 5 | // Config 6 | _scheme: 'auto', 7 | change: { 8 | light: '🌚 Dark', 9 | dark: 'Light 🌝', 10 | }, 11 | buttonsTarget: '.darkmode', 12 | localStorageKey: 'stuffPreferedColorScheme', 13 | 14 | // Init 15 | init() { 16 | this.scheme = this.schemeFromLocalStorage; 17 | this.initSwitchers(); 18 | }, 19 | 20 | // Get color scheme from local storage 21 | get schemeFromLocalStorage() { 22 | if (typeof window.localStorage !== 'undefined') { 23 | if (window.localStorage.getItem(this.localStorageKey) !== null) { 24 | return window.localStorage.getItem(this.localStorageKey); 25 | } 26 | } 27 | return this._scheme; 28 | }, 29 | 30 | // Prefered color scheme 31 | get preferedColorScheme() { 32 | return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; 33 | }, 34 | 35 | // Init switchers 36 | initSwitchers() { 37 | const buttons = document.querySelectorAll(this.buttonsTarget); 38 | buttons.forEach(button => { 39 | button.addEventListener('click', () => { 40 | this.scheme == 'dark' ? this.scheme = 'light' : this.scheme = 'dark'; 41 | }, false); 42 | }); 43 | }, 44 | 45 | // Add new button 46 | addButton(config) { 47 | let button = document.createElement(config.tag); 48 | button.className = config.class; 49 | document.querySelector(config.target).appendChild(button); 50 | }, 51 | 52 | // Set scheme 53 | set scheme(scheme) { 54 | if (scheme == 'auto') { 55 | this.preferedColorScheme == 'light' ? this._scheme = 'light' : this._scheme = 'dark'; 56 | } 57 | else if (scheme == 'dark' || scheme == 'light') { 58 | this._scheme = scheme; 59 | } 60 | this.applyScheme(); 61 | this.schemeToLocalStorage(); 62 | }, 63 | 64 | // Get scheme 65 | get scheme() { 66 | return this._scheme; 67 | }, 68 | 69 | // Apply scheme 70 | applyScheme() { 71 | document.querySelector('html').setAttribute('data-theme', this.scheme); 72 | const buttons = document.querySelectorAll(this.buttonsTarget); 73 | buttons.forEach( 74 | button => { 75 | const text = this.scheme == 'dark' ? this.change.dark : this.change.light; 76 | button.innerHTML = text; 77 | button.setAttribute('aria-label', text.replace(/<[^>]*>?/gm, '')); 78 | } 79 | ); 80 | }, 81 | 82 | // Store scheme to local storage 83 | schemeToLocalStorage() { 84 | if (typeof window.localStorage !== 'undefined') { 85 | window.localStorage.setItem(this.localStorageKey, this.scheme); 86 | } 87 | }, 88 | }; 89 | 90 | export default darkMode; 91 | -------------------------------------------------------------------------------- /dist/js/src/flex.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Grid 3 | */ 4 | 5 | export const flex = { 6 | 7 | // Config 8 | buttons: { 9 | text: { 10 | add: 'Add column', 11 | remove: 'Remove column', 12 | }, 13 | target: '#flex article', 14 | }, 15 | flex: { 16 | current: 4, 17 | min: 1, 18 | max: 12, 19 | flexTarget: '#flex .flex', 20 | codeTarget: '#flex pre code', 21 | }, 22 | 23 | // Init 24 | init() { 25 | this.addButtons(); 26 | this.generateFlex(); 27 | }, 28 | 29 | // Add buttons 30 | addButtons() { 31 | // Insert buttons 32 | let buttons = document.createElement('P'); 33 | buttons.innerHTML = ` 34 | 41 | 42 | `; 48 | document.querySelector(this.buttons.target).before(buttons); 49 | 50 | // Add button listener 51 | document.querySelector('#flex button.add').addEventListener('click', () => { 52 | this.addColumn(); 53 | }, false); 54 | 55 | // Remove button listener 56 | document.querySelector('#flex button.remove').addEventListener('click', () => { 57 | this.removeColumn(); 58 | }, false); 59 | }, 60 | 61 | // Generate grid 62 | generateFlex() { 63 | // Config 64 | let htmlInner = ''; 65 | let codeInner = '<div class="flex">\n'; 66 | 67 | // Build 68 | for (let col = 0; col < this.flex.current; col++) { 69 | htmlInner += '
' + (col + 1) + '
'; 70 | codeInner += ' <div>' + (col + 1) + '</div>\n'; 71 | } 72 | 73 | // Display 74 | codeInner += '</div>'; 75 | document.querySelector(this.flex.flexTarget).innerHTML = htmlInner; 76 | document.querySelector(this.flex.codeTarget).innerHTML = codeInner; 77 | }, 78 | 79 | // Add column 80 | addColumn() { 81 | if (this.flex.current < this.flex.max) { 82 | this.flex.current++; 83 | this.generateGrid(); 84 | } 85 | }, 86 | 87 | // Remove column 88 | removeColumn() { 89 | if (this.grid.current > this.flex.min) { 90 | this.flex.current--; 91 | this.generateFlex(); 92 | } 93 | }, 94 | }; 95 | export default flex; -------------------------------------------------------------------------------- /dist/js/src/material-design-colors.js: -------------------------------------------------------------------------------- 1 | // Source: https://material.io/design/color/the-color-system.html 2 | export const materialDesignColors = { 3 | red: { 4 | 50: '#ffebee', 5 | 100: '#ffcdd2', 6 | 200: '#ef9a9a', 7 | 300: '#e57373', 8 | 400: '#ef5350', 9 | 500: '#f44336', 10 | 600: '#e53935', 11 | 700: '#d32f2f', 12 | 800: '#c62828', 13 | 900: '#b71c1c', 14 | a100: '#ff8a80', 15 | a200: '#ff5252', 16 | a400: '#ff1744', 17 | a700: '#d50000', 18 | inverse: '#FFF', 19 | }, 20 | pink: { 21 | 50: '#fce4ec', 22 | 100: '#f8bbd0', 23 | 200: '#f48fb1', 24 | 300: '#f06292', 25 | 400: '#ec407a', 26 | 500: '#e91e63', 27 | 600: '#d81b60', 28 | 700: '#c2185b', 29 | 800: '#ad1457', 30 | 900: '#880e4f', 31 | a100: '#ff80ab', 32 | a200: '#ff4081', 33 | a400: '#f50057', 34 | a700: '#c51162', 35 | inverse: '#FFF', 36 | }, 37 | purple: { 38 | 50: '#f3e5f5', 39 | 100: '#e1bee7', 40 | 200: '#ce93d8', 41 | 300: '#ba68c8', 42 | 400: '#ab47bc', 43 | 500: '#9c27b0', 44 | 600: '#8e24aa', 45 | 700: '#7b1fa2', 46 | 800: '#6a1b9a', 47 | 900: '#4a148c', 48 | a100: '#ea80fc', 49 | a200: '#e040fb', 50 | a400: '#d500f9', 51 | a700: '#aa00ff', 52 | inverse: '#FFF', 53 | }, 54 | 'deep-purple': { 55 | 50: '#ede7f6', 56 | 100: '#d1c4e9', 57 | 200: '#b39ddb', 58 | 300: '#9575cd', 59 | 400: '#7e57c2', 60 | 500: '#673ab7', 61 | 600: '#5e35b1', 62 | 700: '#512da8', 63 | 800: '#4527a0', 64 | 900: '#311b92', 65 | a100: '#b388ff', 66 | a200: '#7c4dff', 67 | a400: '#651fff', 68 | a700: '#6200ea', 69 | inverse: '#FFF', 70 | }, 71 | indigo: { 72 | 50: '#e8eaf6', 73 | 100: '#c5cae9', 74 | 200: '#9fa8da', 75 | 300: '#7986cb', 76 | 400: '#5c6bc0', 77 | 500: '#3f51b5', 78 | 600: '#3949ab', 79 | 700: '#303f9f', 80 | 800: '#283593', 81 | 900: '#1a237e', 82 | a100: '#8c9eff', 83 | a200: '#536dfe', 84 | a400: '#3d5afe', 85 | a700: '#304ffe', 86 | inverse: '#FFF', 87 | }, 88 | blue: { 89 | 50: '#e3f2fd', 90 | 100: '#bbdefb', 91 | 200: '#90caf9', 92 | 300: '#64b5f6', 93 | 400: '#42a5f5', 94 | 500: '#2196f3', 95 | 600: '#1e88e5', 96 | 700: '#1976d2', 97 | 800: '#1565c0', 98 | 900: '#0d47a1', 99 | a100: '#82b1ff', 100 | a200: '#448aff', 101 | a400: '#2979ff', 102 | a700: '#2962ff', 103 | inverse: '#FFF', 104 | }, 105 | 'light-blue': { 106 | 50: '#e1f5fe', 107 | 100: '#b3e5fc', 108 | 200: '#81d4fa', 109 | 300: '#4fc3f7', 110 | 400: '#29b6f6', 111 | 500: '#03a9f4', 112 | 600: '#039be5', 113 | 700: '#0288d1', 114 | 800: '#0277bd', 115 | 900: '#01579b', 116 | a100: '#80d8ff', 117 | a200: '#40c4ff', 118 | a400: '#00b0ff', 119 | a700: '#0091ea', 120 | inverse: '#FFF', 121 | }, 122 | cyan: { 123 | 50: '#e0f7fa', 124 | 100: '#b2ebf2', 125 | 200: '#80deea', 126 | 300: '#4dd0e1', 127 | 400: '#26c6da', 128 | 500: '#00bcd4', 129 | 600: '#00acc1', 130 | 700: '#0097a7', 131 | 800: '#00838f', 132 | 900: '#006064', 133 | a100: '#84ffff', 134 | a200: '#18ffff', 135 | a400: '#00e5ff', 136 | a700: '#00b8d4', 137 | inverse: '#FFF', 138 | }, 139 | teal: { 140 | 50: '#e0f2f1', 141 | 100: '#b2dfdb', 142 | 200: '#80cbc4', 143 | 300: '#4db6ac', 144 | 400: '#26a69a', 145 | 500: '#009688', 146 | 600: '#00897b', 147 | 700: '#00796b', 148 | 800: '#00695c', 149 | 900: '#004d40', 150 | a100: '#a7ffeb', 151 | a200: '#64ffda', 152 | a400: '#1de9b6', 153 | a700: '#00bfa5', 154 | inverse: '#FFF', 155 | }, 156 | green: { 157 | 50: '#e8f5e9', 158 | 100: '#c8e6c9', 159 | 200: '#a5d6a7', 160 | 300: '#81c784', 161 | 400: '#66bb6a', 162 | 500: '#4caf50', 163 | 600: '#43a047', 164 | 700: '#388e3c', 165 | 800: '#2e7d32', 166 | 900: '#1b5e20', 167 | a100: '#b9f6ca', 168 | a200: '#69f0ae', 169 | a400: '#00e676', 170 | a700: '#00c853', 171 | inverse: '#FFF', 172 | }, 173 | 'light-green': { 174 | 50: '#f1f8e9', 175 | 100: '#dcedc8', 176 | 200: '#c5e1a5', 177 | 300: '#aed581', 178 | 400: '#9ccc65', 179 | 500: '#8bc34a', 180 | 600: '#7cb342', 181 | 700: '#689f38', 182 | 800: '#558b2f', 183 | 900: '#33691e', 184 | a100: '#ccff90', 185 | a200: '#b2ff59', 186 | a400: '#76ff03', 187 | a700: '#64dd17', 188 | inverse: '#FFF', 189 | }, 190 | lime: { 191 | 50: '#f9fbe7', 192 | 100: '#f0f4c3', 193 | 200: '#e6ee9c', 194 | 300: '#dce775', 195 | 400: '#d4e157', 196 | 500: '#cddc39', 197 | 600: '#c0ca33', 198 | 700: '#afb42b', 199 | 800: '#9e9d24', 200 | 900: '#827717', 201 | a100: '#f4ff81', 202 | a200: '#eeff41', 203 | a400: '#c6ff00', 204 | a700: '#aeea00', 205 | inverse: 'rgba(0, 0, 0, 0.75)', 206 | }, 207 | yellow: { 208 | 50: '#fffde7', 209 | 100: '#fff9c4', 210 | 200: '#fff59d', 211 | 300: '#fff176', 212 | 400: '#ffee58', 213 | 500: '#ffeb3b', 214 | 600: '#fdd835', 215 | 700: '#fbc02d', 216 | 800: '#f9a825', 217 | 900: '#f57f17', 218 | a100: '#ffff8d', 219 | a200: '#ffff00', 220 | a400: '#ffea00', 221 | a700: '#ffd600', 222 | inverse: 'rgba(0, 0, 0, 0.75)', 223 | }, 224 | amber: { 225 | 50: '#fff8e1', 226 | 100: '#ffecb3', 227 | 200: '#ffe082', 228 | 300: '#ffd54f', 229 | 400: '#ffca28', 230 | 500: '#ffc107', 231 | 600: '#ffb300', 232 | 700: '#ffa000', 233 | 800: '#ff8f00', 234 | 900: '#ff6f00', 235 | a100: '#ffe57f', 236 | a200: '#ffd740', 237 | a400: '#ffc400', 238 | a700: '#ffab00', 239 | inverse: 'rgba(0, 0, 0, 0.75)', 240 | }, 241 | orange: { 242 | 50: '#fff3e0', 243 | 100: '#ffe0b2', 244 | 200: '#ffcc80', 245 | 300: '#ffb74d', 246 | 400: '#ffa726', 247 | 500: '#ff9800', 248 | 600: '#fb8c00', 249 | 700: '#f57c00', 250 | 800: '#ef6c00', 251 | 900: '#e65100', 252 | a100: '#ffd180', 253 | a200: '#ffab40', 254 | a400: '#ff9100', 255 | a700: '#ff6d00', 256 | inverse: '#FFF', 257 | }, 258 | 'deep-orange': { 259 | 50: '#fbe9e7', 260 | 100: '#ffccbc', 261 | 200: '#ffab91', 262 | 300: '#ff8a65', 263 | 400: '#ff7043', 264 | 500: '#ff5722', 265 | 600: '#f4511e', 266 | 700: '#e64a19', 267 | 800: '#d84315', 268 | 900: '#bf360c', 269 | a100: '#ff9e80', 270 | a200: '#ff6e40', 271 | a400: '#ff3d00', 272 | a700: '#dd2c00', 273 | inverse: '#FFF', 274 | }, 275 | grey: { 276 | 50: '#fafafa', 277 | 100: '#f5f5f5', 278 | 200: '#eeeeee', 279 | 300: '#e0e0e0', 280 | 400: '#bdbdbd', 281 | 500: '#9e9e9e', 282 | 600: '#757575', 283 | 700: '#616161', 284 | 800: '#424242', 285 | 900: '#212121', 286 | inverse: '#FFF', 287 | }, 288 | 'blue-grey': { 289 | 50: '#eceff1', 290 | 100: '#cfd8dc', 291 | 200: '#b0bec5', 292 | 300: '#90a4ae', 293 | 400: '#78909c', 294 | 500: '#607d8b', 295 | 600: '#546e7a', 296 | 700: '#455a64', 297 | 800: '#37474f', 298 | 900: '#263238', 299 | inverse: '#FFF', 300 | }, 301 | }; 302 | 303 | export default materialDesignColors; 304 | -------------------------------------------------------------------------------- /dist/js/src/toggle-navigation.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | export const toggleNavigation = { 4 | 5 | // Config 6 | _state: 'closed-on-mobile', 7 | toggleLink: document.getElementById('toggle-docs-navigation'), 8 | nav: document.querySelector('main > aside > nav'), 9 | 10 | // Init 11 | init() { 12 | this.onToggleClick() 13 | }, 14 | 15 | onToggleClick() { 16 | this.toggleLink.addEventListener('click', event => { 17 | event.preventDefault(); 18 | this.state == 'closed-on-mobile' 19 | ? this.state = 'open' 20 | : this.state = 'closed-on-mobile'; 21 | this.nav.removeAttribute('class'); 22 | this.nav.classList.add(this.state); 23 | }, false); 24 | }, 25 | 26 | // Get state 27 | get state() { 28 | return this._state; 29 | }, 30 | 31 | // Set state 32 | set state(state) { 33 | this._state = state; 34 | }, 35 | }; 36 | 37 | export default toggleNavigation; -------------------------------------------------------------------------------- /dist/js/stuff.js: -------------------------------------------------------------------------------- 1 | // Imports 2 | import darkMode from './src/darkmode'; 3 | // import customDarkmode from "./src/custom-darkmode"; 4 | import toggleNavigation from './src/toggle-navigation'; 5 | import copyButtonLabel from "./src/copy"; 6 | // import flex from "./src/flex"; 7 | 8 | // Theme switcher 9 | darkMode.addButton({ 10 | tag: 'li', 11 | class: 'contrast darkmode', 12 | target: '.darkmode', 13 | }); 14 | 15 | //darkmode 16 | darkMode.init(); 17 | // customDarkmode.init(); 18 | 19 | // Toggle navigation 20 | toggleNavigation.init(); 21 | 22 | // Code doc copy 23 | copyButtonLabel.init(); 24 | 25 | <<<<<<< HEAD 26 | ======= 27 | const activeLink = document.querySelector(`aside a#${props.active}`); 28 | const parentAccordion = activeLink.closest('details'); 29 | activeLink.setAttribute('aria-current', 'page'); 30 | parentAccordion.setAttribute('open', 'true'); 31 | >>>>>>> 4fd3b3c96ee87207cef2a834869eff0449671145 32 | // // Init 33 | // flex.init(); 34 | -------------------------------------------------------------------------------- /dist/js/stuffcustomization.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Customization 3 | * 4 | * Pico.css - https://picocss.com 5 | * Copyright 2019-2022 - Licensed under MIT 6 | */ 7 | 8 | // Imports 9 | import materialDesignColors from './src/material-design-colors.js'; 10 | import colorPicker from './src/color-picker.js'; 11 | 12 | // Color Picker 13 | colorPicker.colors = materialDesignColors; 14 | colorPicker.init(); -------------------------------------------------------------------------------- /dist/js/stuffcustomization.min.js: -------------------------------------------------------------------------------- 1 | "use strict";!function(){var e={colors:null,buttonsTarget:'#customization article[data-theme="generated"]',selectorButton:"#customization button[data-color]",selectorSection:"#customization",buttons:null,generatedStyles:null,init:function(){this.generateButtons(),this.setActiveButton("pink"),this.generateTheme("pink")},generateButtons:function(){var e,a=this,f="",t="";for(e in this.colors)f+=''),t+='\n button[data-color="'.concat(e,'"] {\n background-color: ').concat(this.colors[e][600],';\n }\n [data-theme="light"] button[data-color="').concat(e,'"]:hover,\n [data-theme="light"] button[data-color="').concat(e,'"]:active,\n [data-theme="light"] button[data-color="').concat(e,'"]:focus {\n background-color: ').concat(this.colors[e][700],'; \'\n }\n [data-theme="dark"] button[data-color="').concat(e,'"]:hover,\n [data-theme="dark"] button[data-color="').concat(e,'"]:active,\n [data-theme="dark"] button[data-color="').concat(e,'"]:focus {\n background-color: ').concat(this.colors[e][500],";\n }");var c=document.createElement("FIGURE"),c=(c.innerHTML=f,document.querySelector(this.buttonsTarget).before(c),this.buttons=document.querySelectorAll(this.selectorButton),this.buttons.forEach(function(e){e.addEventListener("click",function(e){e=e.target.getAttribute("data-color");a.setActiveButton(e),a.generateTheme(e)},!1)}),document.createElement("STYLE"));c.setAttribute("title","color-picker"),this.generatedStyles=this.minifyCSS(t),c.innerHTML=this.generatedStyles,document.querySelector("head").appendChild(c)},setActiveButton:function(e){this.buttons.forEach(function(e){e.removeAttribute("class")}),document.querySelector(this.selectorButton+'[data-color="'+e+'"]').setAttribute("class","picked")},generateTheme:function(e){var f=this,a=e,e=this.colors[e],t={".name":a.charAt(0).toUpperCase()+a.substring(1)+" ",".c500":e[500],".c600":e[600],".c700":e[700],".c600-outline-light":this.hexToRgbA(e[600],.125),".c600-outline-dark":this.hexToRgbA(e[600],.25),".inverse":e.inverse},a=(Object.keys(t).forEach(function(a){document.querySelectorAll(f.selectorSection+" "+a).forEach(function(e){e.innerHTML=t[a]})}),'\n [data-theme="generated"] {\n --h4-color: '.concat(e[700],";\n --primary: ").concat(e[600],";\n --primary-hover: ").concat(e[700],";\n --primary-focus: ").concat(this.hexToRgbA(e[600],.125),";\n --primary-inverse: ").concat(e.inverse,';\n }\n @media only screen and (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) [data-theme="generated"] {\n --h4-color: ').concat(e[400],";\n --primary: ").concat(e[600],";\n --primary-hover: ").concat(e[500],";\n --primary-focus: ").concat(this.hexToRgbA(e[600],.25),";\n --primary-inverse: ").concat(e.inverse,';\n }\n }\n [data-theme="dark"] [data-theme="generated"] {\n --h4-color: ').concat(e[500],";\n --primary: ").concat(e[600],";\n --primary-hover: ").concat(e[500],";\n --primary-focus: ").concat(this.hexToRgbA(e[600],.25),";\n --primary-inverse: ").concat(e.inverse,';\n }\n [data-theme="generated"] {\n --form-element-active-border-color: var(--primary);\n --form-element-focus-color: var(--primary-focus);\n --switch-color: var(--primary-inverse);\n --switch-checked-background-color: var(--primary);\n }'));document.querySelector('style[title="color-picker"]').innerHTML=this.generatedStyles+this.minifyCSS(a)},minifyCSS:function(e){return e.replace(/^ +/gm,"")},hexToRgbA:function(e,a){if(/^#([A-Fa-f0-9]{3}){1,2}$/.test(e))return"rgba("+[(e="0x"+(e=3==(e=e.substring(1).split("")).length?[e[0],e[0],e[1],e[1],e[2],e[2]]:e).join(""))>>16&255,e>>8&255,255&e].join(", ")+", "+a+")";throw new Error("Bad Hex")}};e.colors={red:{50:"#ffebee",100:"#ffcdd2",200:"#ef9a9a",300:"#e57373",400:"#ef5350",500:"#f44336",600:"#e53935",700:"#d32f2f",800:"#c62828",900:"#b71c1c",a100:"#ff8a80",a200:"#ff5252",a400:"#ff1744",a700:"#d50000",inverse:"#FFF"},pink:{50:"#fce4ec",100:"#f8bbd0",200:"#f48fb1",300:"#f06292",400:"#ec407a",500:"#e91e63",600:"#d81b60",700:"#c2185b",800:"#ad1457",900:"#880e4f",a100:"#ff80ab",a200:"#ff4081",a400:"#f50057",a700:"#c51162",inverse:"#FFF"},purple:{50:"#f3e5f5",100:"#e1bee7",200:"#ce93d8",300:"#ba68c8",400:"#ab47bc",500:"#9c27b0",600:"#8e24aa",700:"#7b1fa2",800:"#6a1b9a",900:"#4a148c",a100:"#ea80fc",a200:"#e040fb",a400:"#d500f9",a700:"#aa00ff",inverse:"#FFF"},"deep-purple":{50:"#ede7f6",100:"#d1c4e9",200:"#b39ddb",300:"#9575cd",400:"#7e57c2",500:"#673ab7",600:"#5e35b1",700:"#512da8",800:"#4527a0",900:"#311b92",a100:"#b388ff",a200:"#7c4dff",a400:"#651fff",a700:"#6200ea",inverse:"#FFF"},indigo:{50:"#e8eaf6",100:"#c5cae9",200:"#9fa8da",300:"#7986cb",400:"#5c6bc0",500:"#3f51b5",600:"#3949ab",700:"#303f9f",800:"#283593",900:"#1a237e",a100:"#8c9eff",a200:"#536dfe",a400:"#3d5afe",a700:"#304ffe",inverse:"#FFF"},blue:{50:"#e3f2fd",100:"#bbdefb",200:"#90caf9",300:"#64b5f6",400:"#42a5f5",500:"#2196f3",600:"#1e88e5",700:"#1976d2",800:"#1565c0",900:"#0d47a1",a100:"#82b1ff",a200:"#448aff",a400:"#2979ff",a700:"#2962ff",inverse:"#FFF"},"light-blue":{50:"#e1f5fe",100:"#b3e5fc",200:"#81d4fa",300:"#4fc3f7",400:"#29b6f6",500:"#03a9f4",600:"#039be5",700:"#0288d1",800:"#0277bd",900:"#01579b",a100:"#80d8ff",a200:"#40c4ff",a400:"#00b0ff",a700:"#0091ea",inverse:"#FFF"},cyan:{50:"#e0f7fa",100:"#b2ebf2",200:"#80deea",300:"#4dd0e1",400:"#26c6da",500:"#00bcd4",600:"#00acc1",700:"#0097a7",800:"#00838f",900:"#006064",a100:"#84ffff",a200:"#18ffff",a400:"#00e5ff",a700:"#00b8d4",inverse:"#FFF"},teal:{50:"#e0f2f1",100:"#b2dfdb",200:"#80cbc4",300:"#4db6ac",400:"#26a69a",500:"#009688",600:"#00897b",700:"#00796b",800:"#00695c",900:"#004d40",a100:"#a7ffeb",a200:"#64ffda",a400:"#1de9b6",a700:"#00bfa5",inverse:"#FFF"},green:{50:"#e8f5e9",100:"#c8e6c9",200:"#a5d6a7",300:"#81c784",400:"#66bb6a",500:"#4caf50",600:"#43a047",700:"#388e3c",800:"#2e7d32",900:"#1b5e20",a100:"#b9f6ca",a200:"#69f0ae",a400:"#00e676",a700:"#00c853",inverse:"#FFF"},"light-green":{50:"#f1f8e9",100:"#dcedc8",200:"#c5e1a5",300:"#aed581",400:"#9ccc65",500:"#8bc34a",600:"#7cb342",700:"#689f38",800:"#558b2f",900:"#33691e",a100:"#ccff90",a200:"#b2ff59",a400:"#76ff03",a700:"#64dd17",inverse:"#FFF"},lime:{50:"#f9fbe7",100:"#f0f4c3",200:"#e6ee9c",300:"#dce775",400:"#d4e157",500:"#cddc39",600:"#c0ca33",700:"#afb42b",800:"#9e9d24",900:"#827717",a100:"#f4ff81",a200:"#eeff41",a400:"#c6ff00",a700:"#aeea00",inverse:"rgba(0, 0, 0, 0.75)"},yellow:{50:"#fffde7",100:"#fff9c4",200:"#fff59d",300:"#fff176",400:"#ffee58",500:"#ffeb3b",600:"#fdd835",700:"#fbc02d",800:"#f9a825",900:"#f57f17",a100:"#ffff8d",a200:"#ffff00",a400:"#ffea00",a700:"#ffd600",inverse:"rgba(0, 0, 0, 0.75)"},amber:{50:"#fff8e1",100:"#ffecb3",200:"#ffe082",300:"#ffd54f",400:"#ffca28",500:"#ffc107",600:"#ffb300",700:"#ffa000",800:"#ff8f00",900:"#ff6f00",a100:"#ffe57f",a200:"#ffd740",a400:"#ffc400",a700:"#ffab00",inverse:"rgba(0, 0, 0, 0.75)"},orange:{50:"#fff3e0",100:"#ffe0b2",200:"#ffcc80",300:"#ffb74d",400:"#ffa726",500:"#ff9800",600:"#fb8c00",700:"#f57c00",800:"#ef6c00",900:"#e65100",a100:"#ffd180",a200:"#ffab40",a400:"#ff9100",a700:"#ff6d00",inverse:"#FFF"},"deep-orange":{50:"#fbe9e7",100:"#ffccbc",200:"#ffab91",300:"#ff8a65",400:"#ff7043",500:"#ff5722",600:"#f4511e",700:"#e64a19",800:"#d84315",900:"#bf360c",a100:"#ff9e80",a200:"#ff6e40",a400:"#ff3d00",a700:"#dd2c00",inverse:"#FFF"},grey:{50:"#fafafa",100:"#f5f5f5",200:"#eeeeee",300:"#e0e0e0",400:"#bdbdbd",500:"#9e9e9e",600:"#757575",700:"#616161",800:"#424242",900:"#212121",inverse:"#FFF"},"blue-grey":{50:"#eceff1",100:"#cfd8dc",200:"#b0bec5",300:"#90a4ae",400:"#78909c",500:"#607d8b",600:"#546e7a",700:"#455a64",800:"#37474f",900:"#263238",inverse:"#FFF"}},e.init()}(); -------------------------------------------------------------------------------- /dist/js/stuffgrid.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Grid 3 | */ 4 | 5 | const grid = { 6 | 7 | // Config 8 | buttons: { 9 | text: { 10 | add: 'Add column', 11 | remove: 'Remove column', 12 | }, 13 | target: '#grid .card', 14 | }, 15 | grid: { 16 | current: 4, 17 | min: 1, 18 | max: 12, 19 | gridTarget: '#grid .grid', 20 | codeTarget: '#grid pre code', 21 | }, 22 | 23 | // Init 24 | init() { 25 | this.addButtons(); 26 | this.generateGrid(); 27 | }, 28 | 29 | // Add buttons 30 | addButtons() { 31 | // Insert buttons 32 | let buttons = document.createElement('P'); 33 | buttons.innerHTML = ` 34 | 41 | 42 | `; 48 | document.querySelector(this.buttons.target).before(buttons); 49 | 50 | // Add button listener 51 | document.querySelector('#grid button.add').addEventListener('click', () => { 52 | this.addColumn(); 53 | }, false); 54 | 55 | // Remove button listener 56 | document.querySelector('#grid button.remove').addEventListener('click', () => { 57 | this.removeColumn(); 58 | }, false); 59 | }, 60 | 61 | // Generate grid 62 | generateGrid() { 63 | // Config 64 | let htmlInner = ''; 65 | let codeInner = '<div class="grid">\n'; 66 | 67 | // Build 68 | for (let col = 0; col < this.grid.current; col++) { 69 | htmlInner += '
' + (col + 1) + '
'; 70 | codeInner += ' <div>' + (col + 1) + '</div>\n'; 71 | } 72 | 73 | // Display 74 | codeInner += '</div>'; 75 | document.querySelector(this.grid.gridTarget).innerHTML = htmlInner; 76 | document.querySelector(this.grid.codeTarget).innerHTML = codeInner; 77 | }, 78 | 79 | // Add column 80 | addColumn() { 81 | if (this.grid.current < this.grid.max) { 82 | this.grid.current++; 83 | this.generateGrid(); 84 | } 85 | }, 86 | 87 | // Remove column 88 | removeColumn() { 89 | if (this.grid.current > this.grid.min) { 90 | this.grid.current--; 91 | this.generateGrid(); 92 | } 93 | }, 94 | }; 95 | 96 | // Init 97 | grid.init(); -------------------------------------------------------------------------------- /dist/js/stuffgrid.min.js: -------------------------------------------------------------------------------- 1 | "use strict";var grid={buttons:{text:{add:"Add column",remove:"Remove column"},target:"#grid .card"},grid:{current:4,min:1,max:12,gridTarget:"#grid .grid",codeTarget:"#grid pre code"},init:function(){this.addButtons(),this.generateGrid()},addButtons:function(){var t=this,e=document.createElement("P");e.innerHTML='\n \n\n "),document.querySelector(this.buttons.target).before(e),document.querySelector("#grid button.add").addEventListener("click",function(){t.addColumn()},!1),document.querySelector("#grid button.remove").addEventListener("click",function(){t.removeColumn()},!1)},generateGrid:function(){for(var t="",e='<div class="grid">\n',n=0;n"+(n+1)+"",e+=" <div>"+(n+1)+"</div>\n";e+="</div>",document.querySelector(this.grid.gridTarget).innerHTML=t,document.querySelector(this.grid.codeTarget).innerHTML=e},addColumn:function(){this.grid.currentthis.grid.min&&(this.grid.current--,this.generateGrid())}};grid.init(); -------------------------------------------------------------------------------- /dist/js/stuffmodal.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Modal 3 | */ 4 | 5 | // Config 6 | const isOpenClass = 'modal-is-open'; 7 | const openingClass = 'modal-is-opening'; 8 | const closingClass = 'modal-is-closing'; 9 | const animationDuration = 400; // ms 10 | let visibleModal = null; 11 | 12 | 13 | // Toggle modal 14 | const toggleModal = event => { 15 | event.preventDefault(); 16 | const modal = document.getElementById(event.currentTarget.getAttribute('data-target')); 17 | (typeof (modal) != 'undefined' && modal != null) 18 | && isModalOpen(modal) ? closeModal(modal) : openModal(modal) 19 | } 20 | 21 | // Is modal open 22 | const isModalOpen = modal => { 23 | return modal.hasAttribute('open') && modal.getAttribute('open') != 'false' ? true : false; 24 | } 25 | 26 | // Open modal 27 | const openModal = modal => { 28 | if (isScrollbarVisible()) { 29 | document.documentElement.style.setProperty('--scrollbar-width', `${getScrollbarWidth()}px`); 30 | } 31 | document.documentElement.classList.add(isOpenClass, openingClass); 32 | setTimeout(() => { 33 | visibleModal = modal; 34 | document.documentElement.classList.remove(openingClass); 35 | }, animationDuration); 36 | modal.setAttribute('open', true); 37 | } 38 | 39 | // Close modal 40 | const closeModal = modal => { 41 | visibleModal = null; 42 | document.documentElement.classList.add(closingClass); 43 | setTimeout(() => { 44 | document.documentElement.classList.remove(closingClass, isOpenClass); 45 | document.documentElement.style.removeProperty('--scrollbar-width'); 46 | modal.removeAttribute('open'); 47 | }, animationDuration); 48 | } 49 | 50 | // Close with a click outside 51 | document.addEventListener('click', event => { 52 | if (visibleModal != null) { 53 | const modalContent = visibleModal.querySelector('article'); 54 | const isClickInside = modalContent.contains(event.target); 55 | !isClickInside && closeModal(visibleModal); 56 | } 57 | }); 58 | 59 | // Close with Esc key 60 | document.addEventListener('keydown', event => { 61 | if (event.key === 'Escape' && visibleModal != null) { 62 | closeModal(visibleModal); 63 | } 64 | }); 65 | 66 | // Get scrollbar width 67 | const getScrollbarWidth = () => { 68 | 69 | // Creating invisible container 70 | const outer = document.createElement('div'); 71 | outer.style.visibility = 'hidden'; 72 | outer.style.overflow = 'scroll'; // forcing scrollbar to appear 73 | outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps 74 | document.body.appendChild(outer); 75 | 76 | // Creating inner element and placing it in the container 77 | const inner = document.createElement('div'); 78 | outer.appendChild(inner); 79 | 80 | // Calculating difference between container's full width and the child width 81 | const scrollbarWidth = (outer.offsetWidth - inner.offsetWidth); 82 | 83 | // Removing temporary elements from the DOM 84 | outer.parentNode.removeChild(outer); 85 | 86 | return scrollbarWidth; 87 | } 88 | 89 | // Is scrollbar visible 90 | const isScrollbarVisible = () => { 91 | return document.body.scrollHeight > screen.height; 92 | } 93 | -------------------------------------------------------------------------------- /dist/js/stuffmodal.min.js: -------------------------------------------------------------------------------- 1 | "use strict";var isOpenClass="modal-is-open",openingClass="modal-is-opening",closingClass="modal-is-closing",animationDuration=400,visibleModal=null,toggleModal=function(e){e.preventDefault();e=document.getElementById(e.currentTarget.getAttribute("data-target"));(void 0!==e&&null!=e&&isModalOpen(e)?closeModal:openModal)(e)},isModalOpen=function(e){return!(!e.hasAttribute("open")||"false"==e.getAttribute("open"))},openModal=function(e){isScrollbarVisible()&&document.documentElement.style.setProperty("--scrollbar-width","".concat(getScrollbarWidth(),"px")),document.documentElement.classList.add(isOpenClass,openingClass),setTimeout(function(){visibleModal=e,document.documentElement.classList.remove(openingClass)},animationDuration),e.setAttribute("open",!0)},closeModal=function(e){visibleModal=null,document.documentElement.classList.add(closingClass),setTimeout(function(){document.documentElement.classList.remove(closingClass,isOpenClass),document.documentElement.style.removeProperty("--scrollbar-width"),e.removeAttribute("open")},animationDuration)},getScrollbarWidth=(document.addEventListener("click",function(e){null==visibleModal||visibleModal.querySelector("article").contains(e.target)||closeModal(visibleModal)}),document.addEventListener("keydown",function(e){"Escape"===e.key&&null!=visibleModal&&closeModal(visibleModal)}),function(){var e=document.createElement("div"),t=(e.style.visibility="hidden",e.style.overflow="scroll",e.style.msOverflowStyle="scrollbar",document.body.appendChild(e),document.createElement("div")),t=(e.appendChild(t),e.offsetWidth-t.offsetWidth);return e.parentNode.removeChild(e),t}),isScrollbarVisible=function(){return document.body.scrollHeight>screen.height}; -------------------------------------------------------------------------------- /next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | reactStrictMode: true, 4 | 5 | } 6 | 7 | module.exports = nextConfig 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stuffcss", 3 | "version": "1.1.0", 4 | "description": "Minimal CSS Framework for semantic HTML", 5 | "author": "fajarspace", 6 | "main": "index.js", 7 | "homepage": "https://stuffcss.netlify.app", 8 | "license": "MIT", 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/fajarspace/stuff-css.git" 12 | }, 13 | "private": true, 14 | "scripts": { 15 | "dev": "next dev", 16 | "build": "next build", 17 | "start": "next start", 18 | "lint": "next lint", 19 | "watch": "npm-run-all --parallel watch:stuff watch:docs:scss watch:docs:html watch:dist:js --silent", 20 | "builds": "npm-run-all scss:sorter:stuff build:stuff scss:sorter:docs build:docs:css build:dist:js --silent", 21 | "build:docs": "npm-run-all --parallel build:docs:css build:docs:js build:docs:html --silent", 22 | "build:docs:css": "npm-run-all css:compile:docs css:prefix:docs css:minify:docs --silent", 23 | "build:docs:html": "npm-run-all htmlincludes:docs --silent", 24 | "build:dist:js": "npm-run-all js:bundle:dist:stuff js:bundle:dist:stuffcustomization js:babel:dist:stuff js:babel:dist:stuffcustomization js:babel:dist:stuffgrid js:babel:dist:stuffmodal js:minify:dist:stuff js:minify:dist:stuffcustomization js:minify:dist:stuffgrid js:minify:dist:stuffmodal --silent", 25 | "build:stuff": "npm-run-all css:compile:stuff css:prefix:stuff css:minify:stuff --silent", 26 | "css:compile:docs": "sass --style expanded --source-map --embed-sources --no-error-css src/static/scss/:src/static/css/", 27 | "css:compile:stuff": "sass --style expanded --source-map --embed-sources --no-error-css scss/:dist/css/", 28 | "css:minify:docs": "cleancss -O1 --with-rebase --source-map --source-map-inline-sources --batch --batch-suffix .min src/static/css/*.css !src/static/css/*.min.css", 29 | "css:minify:stuff": "cleancss -O1 --with-rebase --source-map --source-map-inline-sources --batch --batch-suffix .min dist/css/*.css dist/css/*/*.css !dist/css/*.min.css !dist/css/*/*.min.css", 30 | "css:prefix:docs": "postcss --config src/static/css --replace src/static/css/*.css !src/static/css/*.min.css", 31 | "css:prefix:stuff": "postcss --config dist/css --replace dist/css/*.css dist/css/*/*.css !dist/css/*.min.css", 32 | "htmlincludes:docs": "html-includes --src docs/src/pages --dest docs --minify minifyJS=true --quiet", 33 | "js:babel:dist:stuff": "babel dist/js/stuff.min.js --out-dir dist/js/ --presets=@babel/preset-env --quiet", 34 | "js:babel:dist:stuffcustomization": "babel dist/js/stuffcustomization.min.js --out-dir dist/js/ --presets=@babel/preset-env --quiet", 35 | "js:babel:dist:stuffgrid": "babel dist/js/stuffgrid.js --out-file dist/js/stuffgrid.min.js --presets=@babel/preset-env --quiet", 36 | "js:babel:dist:stuffmodal": "babel dist/js/stuffmodal.js --out-file dist/js/stuffmodal.min.js --presets=@babel/preset-env --quiet", 37 | "js:bundle:dist:stuff": "rollup dist/js/stuff.js --file dist/js/stuff.min.js --format iife --silent", 38 | "js:bundle:dist:stuffcustomization": "rollup dist/js/stuffcustomization.js --file dist/js/stuffcustomization.min.js --format iife --silent", 39 | "js:minify:dist:stuff": "uglifyjs dist/js/stuff.min.js --compress --mangle --output dist/js/stuff.min.js", 40 | "js:minify:dist:stuffcustomization": "uglifyjs dist/js/stuffcustomization.min.js --compress --mangle --output dist/js/stuffcustomization.min.js", 41 | "js:minify:dist:stuffgrid": "uglifyjs dist/js/stuffgrid.min.js --compress --mangle --output dist/js/stuffgrid.min.js", 42 | "js:minify:dist:stuffmodal": "uglifyjs dist/js/stuffmodal.min.js --compress --mangle --output dist/js/stuffmodal.min.js", 43 | "scss:sorter:docs": "postcss --config scss ./scss/**/*.scss --replace", 44 | "scss:sorter:stuff": "postcss --config scss ./scss/**/*.scss --replace", 45 | "prebuild:docs:html": "echo '[stuffcss] Create documentation pages'", 46 | "prebuild:dist:js": "echo '[stuffcss] Bundle and minify dist .js files'", 47 | "precss:compile:docs": "echo '[stuffcss] Compile documentation .css file'", 48 | "precss:compile:stuff": "echo '[stuffcss] Compile Stuff .css files'", 49 | "precss:minify:docs": "echo '[stuffcss] Minify documentation .css file'", 50 | "precss:minify:stuff": "echo '[stuffcss] Minify Stuff .css files'", 51 | "prescss:sorter:docs": "echo '[stuffcss] Order documentation .scss properties'", 52 | "prescss:sorter:stuff": "echo '[stuffcss] Order Stuff .scss properties'", 53 | "postbuild:docs:css": "echo '\\033[32m[stuffcss] Docs CSS build done\\033[0m'", 54 | "postbuild:docs:html": "echo '\\033[32m[stuffcss] Documentation pages done\\033[0m'", 55 | "postbuild:dist:js": "echo '\\033[32m[stuffcss] Dist .js build done\\033[0m'", 56 | "postbuild:stuff": "echo '\\033[32m[stuffcss] Stuff CSS build done\\033[0m'", 57 | "watch:docs:html": "nodemon --watch docs/src/pages --ext html --exec 'npm run build:docs:html'", 58 | "watch:dist:js": "nodemon --watch dist/js/ --ext js --ignore *.min.js --exec 'npm run build:dist:js'", 59 | "watch:docs:scss": "nodemon --watch src/static/scss/ --ext scss --exec 'npm run build:docs:css'", 60 | "watch:stuff": "nodemon --watch scss/ --ext scss --exec 'npm run build:stuff'" 61 | }, 62 | "dependencies": { 63 | "@babel/cli": "^7.19.3", 64 | "@babel/core": "^7.19.3", 65 | "@babel/preset-env": "^7.19.3", 66 | "@next/font": "13.1.6", 67 | "@types/node": "18.11.18", 68 | "@types/react": "18.0.27", 69 | "@types/react-dom": "18.0.10", 70 | "autoprefixer": "^10.4.13", 71 | "bootstrap": "^5.2.3", 72 | "clean-css-cli": "^5.6.2", 73 | "css-declaration-sorter": "^6.3.1", 74 | "eslint": "8.33.0", 75 | "eslint-config-next": "13.1.6", 76 | "html-includes": "^5.0.0", 77 | "next": "13.1.6", 78 | "nodemon": "^2.0.20", 79 | "npm-run-all": "^4.1.5", 80 | "postcss": "^8.4.21", 81 | "postcss-cli": "^10.1.0", 82 | "postcss-scss": "^4.0.6", 83 | "react": "18.2.0", 84 | "react-bootstrap": "^2.7.0", 85 | "react-dom": "18.2.0", 86 | "react-safe": "^1.3.0", 87 | "rollup": "^3.12.0", 88 | "sass": "^1.57.1", 89 | "typeit-react": "^2.6.4", 90 | "typescript": "4.9.5", 91 | "uglify-js": "^3.17.4" 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fajarspace/Stuff-CSS/4301b51f35190c7479698b0eb28dfd92068b970b/public/favicon.ico -------------------------------------------------------------------------------- /public/next.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/thirteen.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/vercel.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /scss/common/_class.scss: -------------------------------------------------------------------------------- 1 | // Class 2 | // -------------------- 3 | 4 | // Enable
,
,