├── src
├── mixins
│ ├── forms.js
│ ├── lists.js
│ ├── image.js
│ ├── pagination.js
│ ├── box-shadow.js
│ ├── helpers.js
│ ├── border-radius.js
│ ├── grid.js
│ ├── selectors.js
│ └── buttons.js
├── utilities
│ ├── align.js
│ ├── _float.js
│ ├── overflow.js
│ ├── sizing.js
│ ├── display.js
│ ├── shadow.js
│ ├── background.js
│ ├── spacing.js
│ ├── flex.js
│ ├── borders.js
│ └── text.js
├── code.js
├── reboot.js
├── images.js
├── progress.js
├── toasts.js
├── alerts.js
├── grid.js
├── modal.js
├── type.js
├── pagination.js
├── button-group.js
├── carousel.js
├── buttons.js
├── list-group.js
├── tables.js
├── index.js
├── card.js
├── forms.js
└── constants.js
├── .eslintignore
├── index.js
├── jest.config.js
├── babel.config.json
├── .gitignore
├── .npmignore
├── assets
├── logo.old.original.svg
├── logo.old.svg
└── logo.svg
├── .editorconfig
├── examples
└── hello.js
├── package.json
├── .eslintrc
└── README.md
/src/mixins/forms.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules/*
--------------------------------------------------------------------------------
/src/utilities/align.js:
--------------------------------------------------------------------------------
1 | // not supported
2 | // use flex.scss: justifyContent*, alighSelf*, ...
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import BootstrapStyleSheet from './src/';
2 | export default BootstrapStyleSheet;
3 |
--------------------------------------------------------------------------------
/src/mixins/lists.js:
--------------------------------------------------------------------------------
1 | export const mixinListUnstyled = (
2 | // pass
3 | ) => ({
4 | paddingLeft: 0, // useless
5 | });
6 |
--------------------------------------------------------------------------------
/src/mixins/image.js:
--------------------------------------------------------------------------------
1 | export const mixinImageFluid = (
2 | constants,
3 | ) => ({
4 | maxWidth: '100%',
5 | height: 'auto',
6 | });
--------------------------------------------------------------------------------
/src/utilities/_float.js:
--------------------------------------------------------------------------------
1 | // not applicable
2 | // see
3 | // - text: textLeft, textRight, ...
4 | // - flex: alignSelfStart, alignSelfEnd, ...
5 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | bail: 1,
3 | verbose: true,
4 | preset: "react-native",
5 | transform: {
6 | "^.+\\.jsx?$": "babel-jest"
7 | },
8 | };
9 |
--------------------------------------------------------------------------------
/babel.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-env",
4 | "@babel/preset-flow"
5 | ],
6 | "plugins": [
7 | "@babel/plugin-proposal-class-properties"
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/src/mixins/pagination.js:
--------------------------------------------------------------------------------
1 | export const mixinPaginationSizePageLink = (
2 | constants,
3 | paddingY,
4 | paddingX,
5 | fontSize,
6 | lineHeight,
7 | ) => Object.assign({
8 | paddingVertical: paddingY,
9 | paddingHorizontal: paddingX,
10 | fontSize: fontSize,
11 | lineHeight: lineHeight,
12 | });
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *test.*
2 | .npmignore
3 | .expo/
4 | node_modules/
5 | npm-debug.*
6 | *.jks
7 | *.p8
8 | *.p12
9 | *.key
10 | *.mobileprovision
11 | *.orig.*
12 | web-build/
13 | web-report/
14 | package-lock.json
15 | npm-debug.log*
16 | yarn-debug.log*
17 | yarn-error.log*
18 | server.js
19 | server.mjs
20 | .DS_Store
21 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | examples
2 | docs
3 |
4 | *test.*
5 |
6 | node_modules/
7 | .expo/
8 | npm-debug.*
9 | *.jks
10 | *.p8
11 | *.p12
12 | *.key
13 | *.mobileprovision
14 | *.orig.*
15 | web-build/
16 | web-report/
17 | package-lock.json
18 | npm-debug.log*
19 | yarn-debug.log*
20 | yarn-error.log*
21 | server.js
22 | server.mjs
23 | .DS_Store
24 |
25 |
--------------------------------------------------------------------------------
/src/mixins/box-shadow.js:
--------------------------------------------------------------------------------
1 | export const mixinBoxShadow = (
2 | constants,
3 | shadowColor,
4 | shadowOffset,
5 | shadowOpacity,
6 | shadowRadius,
7 | ) => (constants.ENABLE_SHADOWS ? {
8 | shadowColor: shadowColor,
9 | shadowOffset: shadowOffset,
10 | shadowOpacity: shadowOpacity,
11 | shadowRadius: shadowRadius,
12 | elevation: 1,
13 | } : {});
--------------------------------------------------------------------------------
/src/utilities/overflow.js:
--------------------------------------------------------------------------------
1 | export default function getClasses(constants, classes) {
2 | const {
3 | OVERFLOWS,
4 | } = constants;
5 |
6 | const _classes = {
7 | // pass
8 | }
9 |
10 | OVERFLOWS.forEach((item) => {
11 | const classItem = item.charAt(0).toUpperCase() + item.slice(1).toLowerCase();
12 | _classes['overflow' + classItem] = {overflow: item};
13 | });
14 |
15 | return _classes;
16 | };
17 |
--------------------------------------------------------------------------------
/src/utilities/sizing.js:
--------------------------------------------------------------------------------
1 | export default function getClasses(constants, classes) {
2 | const {
3 | SIZES,
4 | SCREENS_INFIXES,
5 | } = constants;
6 |
7 | const _classes = {
8 | mw100: {
9 | maxWidth: '100%',
10 | },
11 |
12 | mh100: {
13 | maxHeight: '100%',
14 | },
15 | };
16 |
17 | // h%screen%size, w%screen%size / ex: h100, w50, hXs100, wLg50, wAuto
18 | SCREENS_INFIXES.forEach((itemScreen) => {
19 | Object.keys(SIZES).forEach(item => _classes['w' + itemScreen + item] = {width: SIZES[item]});
20 | Object.keys(SIZES).forEach(item => _classes['h' + itemScreen + item] = {height: SIZES[item]});
21 | });
22 |
23 | return _classes;
24 | };
25 |
--------------------------------------------------------------------------------
/assets/logo.old.original.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 |
3 | # A special property that should be specified at the top of the file outside of
4 | # any sections. Set to true to stop .editor config file search on current file
5 | root = true
6 |
7 | [*]
8 | # Indentation style
9 | # Possible values - tab, space
10 | indent_style = space
11 |
12 | # Indentation size in single-spaced characters
13 | # Possible values - an integer, tab
14 | indent_size = 2
15 |
16 | # Line ending file format
17 | # Possible values - lf, crlf, cr
18 | end_of_line = lf
19 |
20 | # File character encoding
21 | # Possible values - latin1, utf-8, utf-16be, utf-16le
22 | charset = utf-8
23 |
24 | # Denotes whether to trim whitespace at the end of lines
25 | # Possible values - true, false
26 | trim_trailing_whitespace = true
27 |
28 | # Denotes whether file should end with a newline
29 | # Possible values - true, false
30 | insert_final_newline = true
31 |
--------------------------------------------------------------------------------
/src/code.js:
--------------------------------------------------------------------------------
1 | import { mixinBorderRadius } from './mixins/border-radius';
2 | import { mixinBoxShadow } from './mixins/box-shadow';
3 |
4 | export default function getClasses(constants, classes) {
5 | const {
6 | BORDER_RADIUS_SM,
7 | KBD_PADDING_Y,
8 | KBD_PADDING_X,
9 | KBD_FONT_SIZE,
10 | KBD_COLOR,
11 | KBD_BG,
12 | } = constants;
13 |
14 | const _classes = {
15 |
16 | kbd: Object.assign({
17 | paddingHorizontal: KBD_PADDING_X,
18 | paddingVertical: KBD_PADDING_Y,
19 | color: KBD_COLOR,
20 | backgroundColor: KBD_BG,
21 |
22 | // kbd {
23 | // padding: 0;
24 | // @include font-size(100%);
25 | // font-weight: $nested-kbd-font-weight;
26 | // @include box-shadow(none);
27 | // }
28 | },
29 | mixinBorderRadius(constants, BORDER_RADIUS_SM),
30 | // not supported / inset shadow / mixinBoxShadow(constants, ...),
31 | ),
32 | }
33 |
34 | return _classes;
35 | };
36 |
--------------------------------------------------------------------------------
/src/utilities/display.js:
--------------------------------------------------------------------------------
1 | import { selectorMediaUp } from '../mixins/selectors';
2 |
3 | export default function getClasses(constants, classes) {
4 | const {
5 | SCREENS_INFIXES,
6 | } = constants;
7 |
8 | // experimental
9 | const TYPES = {
10 | 'None': 'none',
11 | 'Flex': 'flex',
12 | // how about extra values?
13 | // inline
14 | // inline-block
15 | // block
16 | // table
17 | // table-cell
18 | // table-row
19 | // inline-flex
20 | };
21 |
22 | const _classes = {
23 | // pass
24 | };
25 |
26 | // d%value / ex: dNone. dFlex
27 | // d%screen%value, / ex: dLgNone
28 | SCREENS_INFIXES.forEach((itemScreen) => {
29 | Object.keys(TYPES).forEach(item => {
30 | _classes['d' + itemScreen + item] = selectorMediaUp(itemScreen, SCREENS_INFIXES, {
31 | display: TYPES[item],
32 | });
33 | });
34 | });
35 |
36 | // dPrint%value, / ex: dPrintNone
37 | Object.keys(TYPES).forEach(item => {
38 | _classes['d' + 'Print' + item] = {
39 | display: TYPES[item],
40 | };
41 | });
42 |
43 | return _classes;
44 | };
45 |
--------------------------------------------------------------------------------
/src/mixins/helpers.js:
--------------------------------------------------------------------------------
1 | import Color from 'color';
2 |
3 | // aka helpers
4 |
5 | export const getDefined = (v, d) => v === undefined ? d : v;
6 |
7 | export const getScreens = (breakpoints, size) => (
8 | // ascending list of screens ("active" breakpoints)
9 | Object.keys(breakpoints)
10 | .sort((a, b) => (breakpoints[a] > breakpoints[b] ? 1 : -1))
11 | .map(item => [item, breakpoints[item]])
12 | .filter(item => item[1] <= size)
13 | .map(item => item[0])
14 | );
15 |
16 | export const colorYiq = (constants, color, dark, light) => {
17 | const c = Color(color);
18 | const { YIG_CONTRASTED_THRESHOLD, YIG_TEXT_DARK, YIG_TEXT_LIGHT } = constants;
19 | const yiq = ((c.red() * 299) + (c.green() * 587) + (c.blue() * 114)) / 1000;
20 | return (yiq >= YIG_CONTRASTED_THRESHOLD) ? (dark || YIG_TEXT_DARK) : (light || YIG_TEXT_LIGHT);
21 | };
22 |
23 | export const colorLevel = (constants, color, level = 0) => (
24 | Color(color || constants.PRIMARY).mix(
25 | Color(level > 0 ? constants.BLACK : constants.WHITE),
26 | Math.abs(level) * constants.THEME_COLOR_INTERVAL,
27 | ).hex()
28 | );
29 |
--------------------------------------------------------------------------------
/examples/hello.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { View, Text } from 'react-native';
3 | import BootstrapStyleSheet from 'react-native-bootstrap-styles';
4 |
5 | const
6 | REM = BootstrapStyleSheet.DIMENSIONS_WIDTH < 360 ? 14 : 16,
7 | BODY_COLOR = '#000022',
8 | TEXT_MUTED = '#888888';
9 |
10 | // custom constants
11 | const constants = {
12 | REM,
13 | BODY_COLOR, TEXT_MUTED,
14 | };
15 |
16 | // custom classes
17 | const classes = {
18 | title: {
19 | color: 'red',
20 | }
21 | };
22 |
23 | const bootstrapStyleSheet = new BootstrapStyleSheet(constants, classes);
24 | const s = bootstrapStyleSheet.create(); // styles
25 | const c = bootstrapStyleSheet.constants; // constants
26 |
27 | class Hello extends Component {
28 |
29 | render() {
30 | return (
31 |
32 |
33 | Hello world!
34 | 🤓🚀🚀🚀
35 |
36 |
37 | );
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/assets/logo.old.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/utilities/shadow.js:
--------------------------------------------------------------------------------
1 | export default function getClasses(constants, classes) {
2 | const {
3 | SHADOW, SHADOW_SM, SHADOW_LG,
4 | SHADOW_COLOR, SHADOW_OPACITY, SHADOW_OFFSET, SHADOW_RADIUS,
5 | SHADOW_COLOR_SM, SHADOW_OPACITY_SM, SHADOW_OFFSET_SM, SHADOW_RADIUS_SM,
6 | SHADOW_COLOR_LG, SHADOW_OPACITY_LG, SHADOW_OFFSET_LG, SHADOW_RADIUS_LG,
7 | } = constants;
8 |
9 | const _classes = {
10 | shadow: Object.assign({}, SHADOW, { // for android
11 | shadowColor: SHADOW_COLOR,
12 | shadowOffset: SHADOW_OFFSET,
13 | shadowOpacity: SHADOW_OPACITY,
14 | shadowRadius: SHADOW_RADIUS,
15 | }),
16 |
17 | shadowSm: Object.assign({}, SHADOW_SM, { // for android
18 | shadowColor: SHADOW_COLOR_SM,
19 | shadowOffset: SHADOW_OFFSET_SM,
20 | shadowOpacity: SHADOW_OPACITY_SM,
21 | shadowRadius: SHADOW_RADIUS_SM,
22 | }),
23 |
24 | shadowLg: Object.assign({}, SHADOW_LG, { // for android
25 | shadowColor: SHADOW_COLOR_LG,
26 | shadowOffset: SHADOW_OFFSET_LG,
27 | shadowOpacity: SHADOW_OPACITY_LG,
28 | shadowRadius: SHADOW_RADIUS_LG,
29 | }),
30 |
31 | shadowNone: Object.assign({}, {elevation: 0}, { // for android
32 | shadowOffset: {width: 0, height: 0},
33 | shadowOpacity: 0,
34 | shadowRadius: 0,
35 | }),
36 | };
37 |
38 | return _classes;
39 | };
40 |
--------------------------------------------------------------------------------
/src/reboot.js:
--------------------------------------------------------------------------------
1 | export default function getClasses(constants, classes) {
2 | const {
3 | BODY_BG,
4 | BODY_COLOR,
5 | FONT_FAMILY_BASE,
6 | FONT_WEIGHT_BASE,
7 | FONT_SIZE_BASE,
8 | LINE_HEIGHT_BASE,
9 | LINK_COLOR,
10 | LINK_DECORATION,
11 | LINK_DECORATION_LINE,
12 | LINK_DECORATION_COLOR,
13 | LINK_DECORATION_STYLE,
14 | LABEL_MARGIN_BOTTOM,
15 | } = constants;
16 |
17 | const _classes = {
18 | text: {
19 | fontFamily: FONT_FAMILY_BASE,
20 | fontSize: FONT_SIZE_BASE,
21 | fontWeight: FONT_WEIGHT_BASE,
22 | lineHeight: LINE_HEIGHT_BASE,
23 | color: BODY_COLOR,
24 | },
25 |
26 | linkText: Object.assign({}, classes.text, {
27 | color: LINK_COLOR,
28 | textDecorationLine: LINK_DECORATION_LINE,
29 | textDecorationColor: LINK_DECORATION_COLOR,
30 | textDecorationStyle: LINK_DECORATION_STYLE,
31 |
32 | // @include hover() {
33 | // color: $link-hover-color;
34 | // text-decoration: $link-hover-decoration;
35 | // }
36 | }),
37 |
38 | image: {
39 | resizeMode: 'contain',
40 | },
41 |
42 | body: {
43 | flex: 1, // experimental
44 | backgroundColor: BODY_BG,
45 | },
46 |
47 | hidden: {
48 | display: 'none',
49 | },
50 | };
51 |
52 | // aliases
53 | _classes.link = _classes.linkText;
54 | _classes.a = _classes.linkText;
55 |
56 | return _classes;
57 | };
58 |
--------------------------------------------------------------------------------
/src/utilities/background.js:
--------------------------------------------------------------------------------
1 | import { colorLevel } from '../mixins/helpers';
2 |
3 | export default function getClasses(constants, classes) {
4 | const {
5 | WHITE,
6 | THEME_COLORS,
7 | } = constants;
8 |
9 | const _classes = {
10 | // @if $enable-gradients {
11 | // @each $color, $value in $theme-colors {
12 | // @include bg-gradient-variant(".bg-gradient-#{$color}", $value);
13 | // }
14 | // }
15 |
16 | bgWhite: {
17 | backgroundColor: WHITE,
18 | },
19 |
20 | bgTransparent: {
21 | backgroundColor: 'transparent',
22 | },
23 | };
24 |
25 | // bg%color / ex: bgPrimary
26 | // bg%colorLight / ex: bgPrimaryLight
27 | // bg%colorDark / ex: bgPrimaryDark
28 | Object.keys(THEME_COLORS).forEach((item) => {
29 | const classColor = item.charAt(0).toUpperCase() + item.slice(1).toLowerCase();
30 | _classes['bg' + classColor] = {backgroundColor: THEME_COLORS[item]};
31 |
32 | // custom
33 | _classes['bg' + classColor + 'Light'] = {backgroundColor: colorLevel(constants, THEME_COLORS[item], -9)};
34 | _classes['bg' + classColor + 'Dark'] = {backgroundColor: colorLevel(constants, THEME_COLORS[item], 9)};
35 |
36 | // custom / experimental
37 | _classes['bg' + classColor + 'Lightest'] = {backgroundColor: colorLevel(constants, THEME_COLORS[item], -11)};
38 | _classes['bg' + classColor + 'Darkest'] = {backgroundColor: colorLevel(constants, THEME_COLORS[item], -11)};
39 | });
40 |
41 | return _classes;
42 | };
43 |
--------------------------------------------------------------------------------
/src/images.js:
--------------------------------------------------------------------------------
1 | import { mixinBorderRadius } from './mixins/border-radius';
2 | import { mixinBoxShadow } from './mixins/box-shadow';
3 | import { mixinImageFluid } from './mixins/image';
4 |
5 | export default function getClasses(constants, classes) {
6 | const {
7 | THUMBNAIL_PADDING,
8 | THUMBNAIL_BG,
9 | THUMBNAIL_BORDER_WIDTH,
10 | THUMBNAIL_BORDER_COLOR,
11 | THUMBNAIL_BORDER_RADIUS,
12 | THUMBNAIL_BOX_SHADOW_COLOR,
13 | THUMBNAIL_BOX_SHADOW_OPACITY,
14 | THUMBNAIL_BOX_SHADOW_OFFSET,
15 | THUMBNAIL_BOX_SHADOW_RADIUS,
16 | } = constants;
17 |
18 | const _classes = {
19 | imgFluid: mixinImageFluid(constants),
20 |
21 | imgThumbnail: Object.assign({
22 | padding: THUMBNAIL_PADDING,
23 | backgroundColor: THUMBNAIL_BG,
24 | borderWidth: THUMBNAIL_BORDER_WIDTH,
25 | borderColor: THUMBNAIL_BORDER_COLOR,
26 | borderStyle: 'solid',
27 | },
28 | mixinBorderRadius(constants, THUMBNAIL_BORDER_RADIUS),
29 | mixinBoxShadow(constants, THUMBNAIL_BOX_SHADOW_COLOR, THUMBNAIL_BOX_SHADOW_OFFSET, THUMBNAIL_BOX_SHADOW_OPACITY, THUMBNAIL_BOX_SHADOW_RADIUS),
30 | mixinImageFluid(constants),
31 | ),
32 |
33 | // .figure {
34 | // // Ensures the caption's text aligns with the image.
35 | // display: inline-block;
36 | // }
37 |
38 | // .figure-img {
39 | // margin-bottom: $spacer / 2;
40 | // line-height: 1;
41 | // }
42 |
43 | // .figure-caption {
44 | // @include font-size($figure-caption-font-size);
45 | // color: $figure-caption-color;
46 | // }
47 | }
48 |
49 | return _classes;
50 | };
51 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-bootstrap-styles",
3 | "keywords": [
4 | "react-component",
5 | "react-native",
6 | "bootstrap",
7 | "bootstrap4",
8 | "style",
9 | "responsive",
10 | "scale",
11 | "component",
12 | "flex",
13 | "grid",
14 | "modal",
15 | "form",
16 | "button"
17 | ],
18 | "version": "4.5.0-q",
19 | "description": "Bootstrap style library for React Native",
20 | "author": "Andrei Vasin (aka Savva) ",
21 | "license": "MIT",
22 | "repository": {
23 | "type": "git",
24 | "url": "git+https://github.com/andrenerd/react-native-bootstrap-styles.git"
25 | },
26 | "bugs": {
27 | "url": "https://github.com/andrenerd/react-native-bootstrap-styles/issues"
28 | },
29 | "homepage": "https://github.com/andrenerd/react-native-bootstrap-styles#readme",
30 | "main": "index.js",
31 | "scripts": {
32 | "start": "react-native start",
33 | "lint": "eslint . --ext .js,.jsx",
34 | "lint-fix": "eslint . --ext .js,.jsx --fix",
35 | "test": "jest"
36 | },
37 | "pre-commit": {
38 | "run": [],
39 | "silent": false
40 | },
41 | "dependencies": {
42 | "color": "^3.1.2",
43 | "events": "latest"
44 | },
45 | "peerDependencies": {
46 | "react": "*",
47 | "react-native": "*"
48 | },
49 | "devDependencies": {
50 | "@babel/core": "^7.8.6",
51 | "@babel/preset-env": "^7.10.2",
52 | "@babel/preset-flow": "^7.10.1",
53 | "babel-eslint": "^8.2.6",
54 | "babel-jest": "^26.0.1",
55 | "babel-plugin-transform-class-properties": "^6.24.1",
56 | "eslint": "^4.19.1",
57 | "eslint-config-airbnb": "^16.1.0",
58 | "eslint-plugin-import": "^2.20.2",
59 | "eslint-plugin-jsx-a11y": "^6.2.3",
60 | "eslint-plugin-react": "^7.19.0",
61 | "jest": "^26.0.1",
62 | "pre-commit": "^1.2.2"
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/utilities/spacing.js:
--------------------------------------------------------------------------------
1 | export default function getClasses(constants, classes) {
2 | const {
3 | SPACERS,
4 | SCREENS_INFIXES,
5 | } = constants;
6 |
7 | const _classes = {
8 | // .m#{$infix}-auto { margin: auto !important; }
9 | // .mt#{$infix}-auto,
10 | // .my#{$infix}-auto {
11 | // margin-top: auto !important;
12 | // }
13 | // .mr#{$infix}-auto,
14 | // .mx#{$infix}-auto {
15 | // margin-right: auto !important;
16 | // }
17 | // .mb#{$infix}-auto,
18 | // .my#{$infix}-auto {
19 | // margin-bottom: auto !important;
20 | // }
21 | // .ml#{$infix}-auto,
22 | // .mx#{$infix}-auto {
23 | // margin-left: auto !important;
24 | // }
25 | };
26 |
27 | // p/m%screen%size
28 | // ex: pySm3, mb2, plXs0
29 | const SPACERS_TYPES = {margin: 'm', padding: 'p'};
30 |
31 | SCREENS_INFIXES.forEach((itemScreen) => {
32 | Object.keys(SPACERS).forEach((itemSpacer) => {
33 | Object.keys(SPACERS_TYPES).forEach((itemType) => {
34 | _classes[SPACERS_TYPES[itemType] + itemScreen + itemSpacer] = {[itemType]: SPACERS[itemSpacer]};
35 | _classes[SPACERS_TYPES[itemType] + 'y' + itemScreen + itemSpacer] = {[itemType + 'Vertical']: SPACERS[itemSpacer]};
36 | _classes[SPACERS_TYPES[itemType] + 'x' + itemScreen + itemSpacer] = {[itemType + 'Horizontal']: SPACERS[itemSpacer]};
37 | _classes[SPACERS_TYPES[itemType] + 't' + itemScreen + itemSpacer] = {[itemType + 'Top']: SPACERS[itemSpacer]};
38 | _classes[SPACERS_TYPES[itemType] + 'b' + itemScreen + itemSpacer] = {[itemType + 'Bottom']: SPACERS[itemSpacer]};
39 | _classes[SPACERS_TYPES[itemType] + 'r' + itemScreen + itemSpacer] = {[itemType + 'Right']: SPACERS[itemSpacer]};
40 | _classes[SPACERS_TYPES[itemType] + 'l' + itemScreen + itemSpacer] = {[itemType + 'Left']: SPACERS[itemSpacer]};
41 | });
42 | });
43 | });
44 |
45 | return _classes;
46 | };
47 |
--------------------------------------------------------------------------------
/src/progress.js:
--------------------------------------------------------------------------------
1 | import { mixinBorderRadius } from './mixins/border-radius';
2 | import { mixinBoxShadow } from './mixins/box-shadow';
3 |
4 | export default function getClasses(constants, classes) {
5 | const {
6 | PROGRESS_HEIGHT,
7 | PROGRESS_FONT_SIZE,
8 | PROGRESS_BG,
9 | PROGRESS_BORDER_RADIUS,
10 | PROGRESS_BOX_SHADOW_COLOR,
11 | PROGRESS_BOX_SHADOW_OFFSET,
12 | PROGRESS_BOX_SHADOW_OPACITY,
13 | PROGRESS_BOX_SHADOW_RADIUS,
14 | PROGRESS_BAR_COLOR,
15 | PROGRESS_BAR_BG,
16 | PROGRESS_BAR_ANIMATION_TIMING,
17 | PROGRESS_BAR_TRANSITION,
18 | } = constants;
19 |
20 | const _classes = {
21 | // @keyframes progress-bar-stripes {
22 | // from { background-position: $progress-height 0; }
23 | // to { background-position: 0 0; }
24 | // }
25 |
26 | progress: Object.assign({
27 | height: PROGRESS_HEIGHT,
28 | overflow: 'hidden',
29 | backgroundColor: PROGRESS_BG,
30 | },
31 | mixinBorderRadius(constants, PROGRESS_BORDER_RADIUS),
32 | // TODO: replace with inner shadow
33 | // https://stackoverflow.com/questions/38084120/box-shadowinset-for-react-native
34 | // mixinBoxShadow(constants, PROGRESS_BOX_SHADOW_COLOR, PROGRESS_BOX_SHADOW_OFFSET, PROGRESS_BOX_SHADOW_OPACITY, PROGRESS_BOX_SHADOW_RADIUS),
35 | ),
36 |
37 | progressBar: {
38 | flex: 1, // display: flex,
39 | flexDirection: 'column',
40 | justifyContent: 'center',
41 | backgroundColor: PROGRESS_BAR_BG,
42 | // @include transition($progress-bar-transition),
43 | },
44 |
45 | progressText: {
46 | color: PROGRESS_BAR_COLOR,
47 | fontSize: PROGRESS_FONT_SIZE,
48 | textAlign: 'center',
49 | },
50 |
51 | // .progress-bar-striped {
52 | // @include gradient-striped();
53 | // background-size: $progress-height $progress-height;
54 | // }
55 |
56 | // .progress-bar-animated {
57 | // animation: progress-bar-stripes $progress-bar-animation-timing;
58 | // }
59 | };
60 |
61 | return _classes;
62 | };
63 |
--------------------------------------------------------------------------------
/src/toasts.js:
--------------------------------------------------------------------------------
1 | import { mixinBorderRadius } from './mixins/border-radius';
2 |
3 | export default function getClasses(constants, classes) {
4 | const {
5 | TOAST_MAX_WIDTH,
6 | TOAST_PADDING_X,
7 | TOAST_PADDING_Y,
8 | TOAST_FONT_SIZE,
9 | TOAST_COLOR,
10 | TOAST_BACKGROUND_COLOR,
11 | TOAST_BORDER_WIDTH,
12 | TOAST_BORDER_COLOR,
13 | TOAST_BORDER_RADIUS,
14 | TOAST_BOX_SHADOW_COLOR,
15 | TOAST_BOX_SHADOW_OPACITY,
16 | TOAST_BOX_SHADOW_OFFSET,
17 | TOAST_BOX_SHADOW_RADIUS,
18 | TOAST_HEADER_COLOR,
19 | TOAST_HEADER_BACKGROUND_COLOR,
20 | TOAST_HEADER_BORDER_COLOR,
21 | } = constants;
22 |
23 | const _classes = {
24 |
25 | toast: Object.assign({
26 | maxWidth: TOAST_MAX_WIDTH,
27 | overflow: 'hidden', // cheap rounded corners on nested items
28 | color: TOAST_COLOR,
29 | backgroundColor: TOAST_BACKGROUND_COLOR,
30 | borderWidth: TOAST_BORDER_WIDTH,
31 | borderStyle: 'solid',
32 | borderColor: TOAST_BORDER_COLOR,
33 | shadowColor: TOAST_BOX_SHADOW_COLOR,
34 | shadowOffset: TOAST_BOX_SHADOW_OFFSET,
35 | shadowOpacity: TOAST_BOX_SHADOW_OPACITY,
36 | shadowRadius: TOAST_BOX_SHADOW_RADIUS,
37 | opacity: 0,
38 | // not supported / backdrop-filter: blur(10px); // check: BlurView, react-native-blur
39 | // not supported / backgroundClip: padding-box,
40 | },
41 | mixinBorderRadius(constants, TOAST_BORDER_RADIUS),
42 | // @include font-size($toast-font-size);
43 | ),
44 |
45 | toastNotLastChild: (nOrBool, length) => selectorLastChild(nOrBool, length, {
46 | marginBottom: TOAST_PADDING_X,
47 | }),
48 |
49 | toastHeader: {
50 | alignItems: 'center',
51 | paddingVertical: TOAST_PADDING_Y,
52 | paddingHorizontal: TOAST_PADDING_X,
53 | color: TOAST_HEADER_COLOR,
54 | backgroundColor: TOAST_HEADER_BACKGROUND_COLOR,
55 | borderWidth: TOAST_BORDER_WIDTH,
56 | borderStyle: 'solid',
57 | borderColor: TOAST_HEADER_BORDER_COLOR,
58 | // not supported / background-clip: padding-box;
59 | },
60 |
61 | toastBody: {
62 | padding: TOAST_PADDING_X, // apply to both vertical and horizontal
63 | },
64 |
65 | toastShowing: {
66 | opacity: 1,
67 | },
68 |
69 | toastShow: {
70 | opacity: 1,
71 | },
72 |
73 | toastHide: {
74 | display: 'none',
75 | },
76 | };
77 |
78 | return _classes;
79 | };
80 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": [
4 | "react-app",
5 | "airbnb"
6 | ],
7 | "env": {
8 | "es6": true,
9 | "browser": true,
10 | "node": true
11 | },
12 | "rules": {
13 | "react/jsx-filename-extension": 0,
14 | "react/forbid-prop-types": 0,
15 | "react/prefer-stateless-function": 0,
16 | "react/prop-types": 0,
17 | "react/require-default-props": 0,
18 | "react/no-array-index-key": 0,
19 | "react/sort-comp": 0,
20 | "react/no-did-mount-set-state": 0,
21 | "react/no-multi-comp": 0,
22 | "react/jsx-no-undef": 0,
23 | "react/no-unused-prop-types": 0,
24 | "react/no-unused-state": 0,
25 | "react/default-props-match-prop-types": 0,
26 | "react/jsx-no-bind": 0,
27 | "react/jsx-closing-bracket-location": 0,
28 | "react/style-prop-object": 0,
29 | "jsx-a11y/anchor-is-valid": 0,
30 | "jsx-a11y/href-no-hash": 0,
31 | "jsx-a11y/click-events-have-key-events": 0,
32 | "jsx-a11y/no-static-element-interactions": 0,
33 | "jsx-a11y/accessible-emoji": 0,
34 | "jsx-a11y/label-has-for": 0,
35 | "prefer-destructuring": 0,
36 | "prefer-promise-reject-errors": 0,
37 | "prefer-template": 0,
38 | "import/first": 0,
39 | "import/prefer-default-export": 0,
40 | "import/no-extraneous-dependencies": 0,
41 | "import/no-unresolved": 0,
42 | "import/extensions": 0,
43 | "import/newline-after-import": 0,
44 | "camelcase": 0,
45 | "no-empty-pattern": 0,
46 | "no-param-reassign": 0,
47 | "no-shadow": 0,
48 | "no-class-assign": 0,
49 | "no-console": 0,
50 | "no-debugger": 0,
51 | "no-plusplus": 0,
52 | "no-undef": 0,
53 | "no-unused-vars": 0,
54 | "no-unused-expressions": 0,
55 | "no-underscore-dangle": 0,
56 | "no-useless-escape": 0,
57 | "no-useless-constructor": 0,
58 | "no-use-before-define": 0,
59 | "no-throw-literal": 0,
60 | "no-return-assign": 0,
61 | "no-mixed-operators": 0,
62 | "no-restricted-properties": 0,
63 | "no-case-declarations": 0,
64 | "max-len": 0,
65 | "one-var": 0,
66 | "quotes": 0,
67 | "quote-props": 0,
68 | "consistent-return": 0,
69 | "class-methods-use-this": 0,
70 | "function-paren-newline": 0,
71 | "global-require": 0,
72 | "object-curly-spacing": 0,
73 | "object-curly-newline": 0,
74 | "object-property-newline": 0,
75 | "object-shorthand": 0,
76 | "padded-blocks": 0,
77 | "eol-last": 0,
78 | "eqeqeq": 0,
79 | "indent": 0,
80 | "dot-notation": 0,
81 | "default-case": 0
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/utilities/flex.js:
--------------------------------------------------------------------------------
1 | export default function getClasses(constants, classes) {
2 | const {
3 | GRID_BREAKPOINTS,
4 | GRID_COLUMNS,
5 | SCREENS_INFIXES,
6 | } = constants;
7 |
8 | const _classes = {
9 | // todo: make it "screen" aware
10 | justifyContentStart: {justifyContent: 'flex-start'},
11 | justifyContentEnd: {justifyContent: 'flex-end'},
12 | justifyContentCenter: {justifyContent: 'center'},
13 | justifyContentBetween: {justifyContent: 'space-between'},
14 | justifyContentAround: {justifyContent: 'space-around'},
15 |
16 | alignItemsStart: {alignItems: 'flex-start'},
17 | alignItemsEnd: {alignItems: 'flex-end'},
18 | alignItemsCenter: {alignItems: 'center'},
19 | alignItemsBaseline: {alignItems: 'baseline'},
20 | alignItemsStretch: {alignItems: 'stretch'},
21 |
22 | alignContentStart: {alignContent: 'flex-start'},
23 | alignContentEnd: {alignContent: 'flex-end'},
24 | alignContentCenter: {alignContent: 'center'},
25 | alignContentBetween: {alignContent: 'space-between'},
26 | alignContentAround: {alignContent: 'space-around'},
27 | alignContentStretch: {alignContent: 'stretch'},
28 |
29 | alignSelfAuto: {alignSelf: 'auto'},
30 | alignSelfStart: {alignSelf: 'flex-start'},
31 | alignSelfEnd: {alignSelf: 'flex-end'},
32 | alignSelfCenter: {alignSelf: 'center'},
33 | alignSelfBaseline: {alignSelf: 'baseline'},
34 | alignSelfStretch: {alignSelf: 'stretch'},
35 | };
36 |
37 | // flex%screen%columns
38 | // flex%screen (synonym to flex%screen1)
39 | SCREENS_INFIXES.forEach((itemScreen) => {
40 | Array.from(Array(GRID_COLUMNS + 1).keys()).forEach(item => _classes['flex' + itemScreen + (item + 1)] = {flex: item + 1});
41 | _classes['flex' + itemScreen] = _classes['flex' + itemScreen + 1]; // experimental
42 |
43 | _classes['flex' + itemScreen + 'Row'] = {flexDirection: 'row'};
44 | _classes['flex' + itemScreen + 'Column'] = {flexDirection: 'column'};
45 | _classes['flex' + itemScreen + 'RowReverse'] = {flexDirection: 'row-reverse'};
46 | _classes['flex' + itemScreen + 'ColumnReverse'] = {flexDirection: 'column-reverse'};
47 |
48 | _classes['flex' + itemScreen + 'Wrap'] = {flexWrap: 'wrap'};
49 | _classes['flex' + itemScreen + 'Nowrap'] = {flexWrap: 'nowrap'};
50 | // reserved / .flex#{$infix}-fill { flex: 1 1 auto !important; }
51 | _classes['flex' + itemScreen + 'Grow0'] = {flexGrow: 0};
52 | _classes['flex' + itemScreen + 'Shrink0'] = {flexShrink: 0};
53 | _classes['flex' + itemScreen + 'Shrink1'] = {flexShrink: 1};
54 | });
55 |
56 | return _classes;
57 | };
58 |
--------------------------------------------------------------------------------
/src/mixins/border-radius.js:
--------------------------------------------------------------------------------
1 | import { getDefined } from './helpers';
2 |
3 | // TODO: think to drop "constants" as param for all the mixins
4 |
5 | export const mixinBorderRadius = (
6 | constants,
7 | allOrTopLeftRadius,
8 | topRightRadius,
9 | bottomRightRadius,
10 | bottomLeftRadius,
11 | ) => (constants.ENABLE_ROUNDED ? (
12 | arguments.length <= 2 ? {
13 | borderRadius: 1, // getDefined(allOrTopLeftRadius, constants.BORDER_RADIUS),
14 | } : {
15 | borderTopLeftRadius: getDefined(allOrTopLeftRadius, constants.BORDER_RADIUS),
16 | borderTopRightRadius: getDefined(topRightRadius, constants.BORDER_RADIUS),
17 | borderBottomRightRadius: getDefined(bottomRightRadius, constants.BORDER_RADIUS),
18 | borderBottomLeftRadius: getDefined(bottomLeftRadius, constants.BORDER_RADIUS),
19 | }
20 | ) : {});
21 |
22 | export const mixinBorderTopRadius = (
23 | constants,
24 | radius,
25 | ) => (constants.ENABLE_ROUNDED ? {
26 | borderTopLeftRadius: getDefined(radius, constants.BORDER_RADIUS),
27 | borderTopRightRadius: getDefined(radius, constants.BORDER_RADIUS),
28 | } : {});
29 |
30 | export const mixinBorderBottomRadius = (
31 | constants,
32 | radius,
33 | ) => (constants.ENABLE_ROUNDED ? {
34 | borderBottomLeftRadius: getDefined(radius, constants.BORDER_RADIUS),
35 | borderBottomRightRadius: getDefined(radius, constants.BORDER_RADIUS),
36 | } : {});
37 |
38 | export const mixinBorderLeftRadius = (
39 | constants,
40 | radius,
41 | ) => (constants.ENABLE_ROUNDED ? {
42 | borderTopLeftRadius: getDefined(radius, constants.BORDER_RADIUS),
43 | borderBottomLeftRadius: getDefined(radius, constants.BORDER_RADIUS),
44 | } : {});
45 |
46 | export const mixinBorderRightRadius = (
47 | constants,
48 | radius,
49 | ) => (constants.ENABLE_ROUNDED ? {
50 | borderTopRightRadius: getDefined(radius, constants.BORDER_RADIUS),
51 | borderBottomRightRadius: getDefined(radius, constants.BORDER_RADIUS),
52 | } : {});
53 |
54 | export const mixinBorderTopLeftRadius = (
55 | constants,
56 | radius,
57 | ) => (constants.ENABLE_ROUNDED ? {
58 | borderTopLeftRadius: getDefined(radius, constants.BORDER_RADIUS),
59 | } : {});
60 |
61 | export const mixinBorderTopRightRadius = (
62 | constants,
63 | radius,
64 | ) => (constants.ENABLE_ROUNDED ? {
65 | borderTopRightRadius: getDefined(radius, constants.BORDER_RADIUS),
66 | } : {});
67 |
68 | export const mixinBorderBottomLeftRadius = (
69 | constants,
70 | radius,
71 | ) => (constants.ENABLE_ROUNDED ? {
72 | borderBottomLeftRadius: getDefined(radius, constants.BORDER_RADIUS),
73 | } : {});
74 |
75 | export const mixinBorderBottomRightRadius = (
76 | constants,
77 | radius,
78 | ) => (constants.ENABLE_ROUNDED ? {
79 | borderBottomRightRadius: getDefined(radius, constants.BORDER_RADIUS),
80 | } : {});
81 |
--------------------------------------------------------------------------------
/src/alerts.js:
--------------------------------------------------------------------------------
1 | import Color from 'color';
2 |
3 | import { mixinBorderRadius } from './mixins/border-radius';
4 | import { colorLevel } from './mixins/helpers';
5 |
6 | export default function getClasses(constants, classes) {
7 | const {
8 | THEME_COLORS,
9 | ALERT_PADDING_Y,
10 | ALERT_PADDING_X,
11 | ALERT_MARGIN_BOTTOM,
12 | ALERT_BORDER_RADIUS,
13 | ALERT_LINK_FONT_WEIGHT,
14 | ALERT_BORDER_WIDTH,
15 | ALERT_BG_LEVEL,
16 | ALERT_BORDER_LEVEL,
17 | ALERT_COLOR_LEVEL,
18 |
19 | CLOSE_FONT_SIZE,
20 | CLOSE_FONT_WEIGHT,
21 | CLOSE_COLOR,
22 | } = constants;
23 |
24 | const _classes = {
25 | alert: Object.assign({
26 | position: 'relative',
27 | width: '100%',
28 | paddingVertical: ALERT_PADDING_Y,
29 | paddingHorizontal: ALERT_PADDING_X,
30 | marginBottom: ALERT_MARGIN_BOTTOM,
31 | borderWidth: ALERT_BORDER_WIDTH,
32 | borderStyle: 'solid',
33 | borderColor: 'transparent', // is it ok?
34 | },
35 | mixinBorderRadius(constants, ALERT_BORDER_RADIUS),
36 | ),
37 |
38 | alertText: Object.assign({}, classes.text, {
39 | // pass
40 | }),
41 |
42 | alertLink: {
43 | fontWeight: ALERT_LINK_FONT_WEIGHT,
44 | },
45 |
46 | // obsoleted
47 | // .alert-heading {
48 | // // Specified to prevent conflicts of changing $headings-color
49 | // color: inherit;
50 | // }
51 |
52 | alertDismissible: {
53 | paddingRight: CLOSE_FONT_SIZE + ALERT_PADDING_X * 2,
54 | },
55 |
56 | alertDismissibleClose: {
57 | position: 'absolute',
58 | top: 0,
59 | right: 0,
60 | paddingVertical: ALERT_PADDING_Y,
61 | paddingHorizontal: ALERT_PADDING_X,
62 | // TODO: color: inherit;
63 | },
64 | };
65 |
66 | // alert%color / ex: alertPrimary
67 | Object.keys(THEME_COLORS).forEach((item) => {
68 | const classColor = item.charAt(0).toUpperCase() + item.slice(1).toLowerCase();
69 |
70 | const background = colorLevel(constants, THEME_COLORS[item], ALERT_BG_LEVEL); // theme-color-level($color, $alert-bg-level)
71 | const border = colorLevel(constants, THEME_COLORS[item], ALERT_BORDER_LEVEL); // theme-color-level($color, $alert-border-level)
72 | const color = colorLevel(constants, THEME_COLORS[item], ALERT_COLOR_LEVEL); // theme-color-level($color, $alert-color-level)
73 |
74 | classes['alert' + classColor] = {
75 | borderColor: border,
76 | backgroundColor: background, // @include gradient-bg($background);
77 | }
78 |
79 | classes['alert' + classColor + 'Text'] = {
80 | color: color,
81 | }
82 |
83 | classes['alert' + classColor + 'Hr'] = {
84 | borderTopColor: Color(border).darken(0.05).rgb().string(),
85 | }
86 |
87 | classes['alert' + classColor + 'Link'] = {
88 | color: Color(color).darken(0.10).rgb().string(),
89 | }
90 | });
91 |
92 | return _classes;
93 | };
94 |
--------------------------------------------------------------------------------
/src/utilities/borders.js:
--------------------------------------------------------------------------------
1 | export default function getClasses(constants, classes) {
2 | const {
3 | WHITE,
4 | THEME_COLORS,
5 | BORDER_COLOR,
6 | BORDER_WIDTH,
7 | BORDER_RADIUS,
8 | BORDER_RADIUS_SM,
9 | BORDER_RADIUS_LG,
10 | ROUNDED_PILL,
11 | } = constants;
12 |
13 | const _classes = {
14 | // experimental
15 | border: {
16 | borderColor: BORDER_COLOR,
17 | borderWidth: BORDER_WIDTH,
18 | borderStyle: 'solid',
19 | },
20 |
21 | borderTop: {
22 | borderColor: BORDER_COLOR,
23 | borderTopWidth: BORDER_WIDTH,
24 | borderStyle: 'solid',
25 | },
26 |
27 | borderRight: {
28 | borderColor: BORDER_COLOR,
29 | borderRightWidth: BORDER_WIDTH,
30 | borderStyle: 'solid',
31 | },
32 |
33 | borderBottom: {
34 | borderColor: BORDER_COLOR,
35 | borderBottomWidth: BORDER_WIDTH,
36 | borderStyle: 'solid',
37 | },
38 |
39 | borderLeft: {
40 | borderColor: BORDER_COLOR,
41 | borderLeftWidth: BORDER_WIDTH,
42 | borderStyle: 'solid',
43 | },
44 |
45 | border0: {borderWidth: 0},
46 | borderTop0: {borderTopWidth: 0},
47 | borderRight0: {borderRightWidth: 0},
48 | borderBottom0: {borderBottomWidth: 0},
49 | borderLeft0: {borderLeftWidth: 0},
50 |
51 | borderWhite: {borderColor: WHITE},
52 |
53 | // DEPRECATED
54 | borderRounded: {
55 | borderRadius: BORDER_RADIUS,
56 | },
57 |
58 | roundedSm: {
59 | borderRadius: BORDER_RADIUS_SM,
60 | },
61 |
62 | rounded: {
63 | borderRadius: BORDER_RADIUS,
64 | },
65 |
66 | roundedTop: {
67 | borderTopLeftRadius: BORDER_RADIUS,
68 | borderTopRightRadius: BORDER_RADIUS,
69 | },
70 |
71 | roundedRight: {
72 | borderTopRightRadius: BORDER_RADIUS,
73 | borderBottomRightRadius: BORDER_RADIUS,
74 | },
75 |
76 | roundedBottom: {
77 | borderBottomRightRadius: BORDER_RADIUS,
78 | borderBottomLeftRadius: BORDER_RADIUS,
79 | },
80 |
81 | roundedLeft: {
82 | borderTopLeftRadius: BORDER_RADIUS,
83 | borderBottomLeftRadius: BORDER_RADIUS,
84 | },
85 |
86 | roundedLg: {
87 | borderRadius: BORDER_RADIUS_LG,
88 | },
89 |
90 | // workaround / number, not percentage, accepted only
91 | roundedCircle: widthHeight => widthHeight / 2,
92 |
93 | roundedPill: {
94 | borderRadius: ROUNDED_PILL,
95 | },
96 |
97 | rounded0: {
98 | borderRadius: 0,
99 | },
100 | };
101 |
102 | // border%color / ex: borderPrimary
103 | Object.keys(THEME_COLORS).forEach((item) => {
104 | const classColor = item.charAt(0).toUpperCase() + item.slice(1).toLowerCase();
105 | _classes['border' + classColor] = {borderColor: THEME_COLORS[item]};
106 | });
107 |
108 | return _classes;
109 | };
110 |
--------------------------------------------------------------------------------
/src/mixins/grid.js:
--------------------------------------------------------------------------------
1 | // import { mixinBorderRadius } from './border-radius';
2 |
3 | export const mixinMakeContainer = (
4 | constants,
5 | gutter = null,
6 | ) => (constants.ENABLE_GRID_CLASSES ? {
7 | width: '100%', // experimental
8 | flexDirection: 'column',
9 | paddingRight: (gutter || constants.GRID_GUTTER_WIDTH) / 2,
10 | paddingLeft: (gutter || constants.GRID_GUTTER_WIDTH) / 2,
11 | marginRight: 'auto', // experimental
12 | marginLeft: 'auto', // experimental
13 | } : {});
14 |
15 | export const mixinMakeContainerMaxWidths = (
16 | constants,
17 | screen = null,
18 | ) => (constants.ENABLE_GRID_CLASSES ? {
19 | maxWidth: constants.CONTAINER_MAX_WIDTHS[screen || constants.SCREEN],
20 | } : {});
21 |
22 | export const mixinMakeRow = (
23 | constants,
24 | gutter = null,
25 | ) => (constants.ENABLE_GRID_CLASSES ? {
26 | flexWrap: 'wrap',
27 | marginRight: -(gutter || constants.GRID_GUTTER_WIDTH) / 2,
28 | marginLeft: -(gutter || constants.GRID_GUTTER_WIDTH) / 2,
29 | } : {});
30 |
31 | // RESERVED
32 | // export const mixinMakeColReady = (
33 | // constants,
34 | // gutter = null,
35 | // ) => (constants.ENABLE_GRID_CLASSES ? {
36 | // paddingRight: (gutter || constants.GRID_GUTTER_WIDTH) / 2,
37 | // paddingLeft: (gutter || constants.GRID_GUTTER_WIDTH) / 2,
38 | // } : {});
39 |
40 | // experimental
41 | export const mixinMakeCol = (
42 | constants,
43 | gutter = null,
44 | ) => (constants.ENABLE_GRID_CLASSES ? {
45 | flexDirection: 'column', // critical / why? / TODO: document it
46 | // OBSOLETED / flexBasis: 0, // harmful
47 | // OBSOLETED / flexGrow: 1, // harmful
48 | paddingRight: (gutter || constants.GRID_GUTTER_WIDTH) / 2,
49 | paddingLeft: (gutter || constants.GRID_GUTTER_WIDTH) / 2,
50 | minWidth: 0, // excessive?
51 | maxWidth: '100%', // excessive?
52 | } : {});
53 |
54 | // RESERVED
55 | // @mixin make-col($size, $columns: $grid-columns) {
56 | // flex: 0 0 percentage($size / $columns);
57 | // // Add a `max-width` to ensure content within each column does not blow out
58 | // // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari
59 | // // do not appear to require this.
60 | // max-width: percentage($size / $columns);
61 | // }
62 |
63 | // RESERVED
64 | // @mixin make-col-auto() {
65 | // flex: 0 0 auto;
66 | // width: auto;
67 | // max-width: 100%; // Reset earlier grid tiers
68 | // }
69 |
70 | // SKIPPED
71 | // @mixin make-col-offset($size, $columns: $grid-columns) {
72 | // $num: $size / $columns;
73 | // margin-left: if($num == 0, 0, percentage($num));
74 | // }
75 |
76 | // SKIPPED
77 | // // Row columns
78 | // //
79 | // // Specify on a parent element(e.g., .row) to force immediate children into NN
80 | // // numberof columns. Supports wrapping to new lines, but does not do a Masonry
81 | // // style grid.
82 | // @mixin row-cols($count) {
83 | // & > * {
84 | // flex: 0 0 100% / $count;
85 | // max-width: 100% / $count;
86 | // }
87 | // }
88 |
--------------------------------------------------------------------------------
/src/grid.js:
--------------------------------------------------------------------------------
1 | import { mixinMakeContainer, mixinMakeContainerMaxWidths } from './mixins/grid';
2 | import { mixinMakeRow, mixinMakeCol } from './mixins/grid';
3 | import { getScreens } from './mixins/helpers';
4 |
5 | export default function getClasses(constants, classes) {
6 | const {
7 | ENABLE_GRID_CLASSES,
8 | GRID_BREAKPOINTS,
9 | GRID_COLUMNS,
10 | GRID_GUTTER_WIDTH,
11 | SCREENS_INFIXES,
12 | // OBSOLETED / SCREEN,
13 | } = constants;
14 |
15 | const _classes = ENABLE_GRID_CLASSES ? {
16 |
17 | // TODO: add later
18 | // container: Object.assign({},
19 | // mixinMakeContainer(constants),
20 | // mixinMakeContainerMaxWidths(constants),
21 | // ),
22 |
23 | containerFluid: Object.assign({},
24 | mixinMakeContainer(constants),
25 | ),
26 |
27 | noGutters: {
28 | marginRight: 0,
29 | marginLeft: 0,
30 | },
31 |
32 | noGuttersCol: {
33 | paddingRight: 0,
34 | paddingLeft: 0,
35 | },
36 |
37 | // experimental / in use
38 | Gutters: {
39 | marginRight: -GRID_GUTTER_WIDTH / 2,
40 | marginLeft: -GRID_GUTTER_WIDTH / 2,
41 | },
42 |
43 | // experimental / in use
44 | GuttersCol: {
45 | paddingRight: GRID_GUTTER_WIDTH / 2,
46 | paddingLeft: GRID_GUTTER_WIDTH / 2,
47 | },
48 | } : {};
49 |
50 | // container%screen / ex: containerMd
51 | if (ENABLE_GRID_CLASSES) {
52 | SCREENS_INFIXES.forEach((item) => {
53 | _classes['container' + item] = Object.assign({},
54 | mixinMakeContainer(constants),
55 | mixinMakeContainerMaxWidths(constants, item),
56 | );
57 | });
58 | }
59 |
60 | if (ENABLE_GRID_CLASSES) {
61 | const SCREENS_INFIXES_ALL = [''].concat(Object.keys(GRID_BREAKPOINTS));
62 | const gridColumnsArray = Array.from(Array(GRID_COLUMNS).keys());
63 |
64 | SCREENS_INFIXES_ALL.forEach((itemScreen) => {
65 | _classes['row' + itemScreen] = Object.assign(mixinMakeRow(constants),
66 | SCREENS_INFIXES.indexOf(itemScreen) > -1 ? { // dirty
67 | flexDirection: 'row',
68 | // more?
69 | } : {}
70 | );
71 | });
72 |
73 | SCREENS_INFIXES_ALL.forEach((itemScreen) => {
74 | GRID_COLUMNS && gridColumnsArray.forEach(item => {
75 | _classes['col' + itemScreen + (item || '')] = Object.assign(mixinMakeCol(constants),
76 | SCREENS_INFIXES.indexOf(itemScreen) > -1 ? { // dirty
77 | flex: item || 1,
78 | // more?
79 | } : {}
80 | );
81 | });
82 |
83 | // SKIPPED
84 | // _classes['col' + itemScreen + 'Auto'] = mixinMakeCol(constants);
85 | });
86 |
87 | // Row columns
88 | // .row-cols-*
89 | // SKIPPED
90 |
91 | // Offsetting columns
92 | // .offset-*-*
93 | // SKIPPED
94 |
95 | // Reordering
96 | // .order-*-*
97 | // SKIPPED
98 | }
99 |
100 | return _classes;
101 | };
102 |
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/src/utilities/text.js:
--------------------------------------------------------------------------------
1 | import Color from 'color';
2 | import { colorLevel } from '../mixins/helpers';
3 | import { selectorMediaUp } from '../mixins/selectors';
4 |
5 | export default function getClasses(constants, classes) {
6 | const {
7 | WHITE,
8 | BLACK,
9 | BODY_COLOR,
10 | THEME_COLORS,
11 | SCREENS_INFIXES,
12 | TEXT_MUTED,
13 | FONT_FAMILY_BASE,
14 | FONT_FAMILY_BASE_LIGHT, // experimental
15 | FONT_FAMILY_BASE_BOLD, // experimental
16 | FONT_FAMILY_MONOSPACE,
17 | FONT_WEIGHT_NORMAL,
18 | FONT_WEIGHT_LIGHT,
19 | FONT_WEIGHT_BOLD,
20 | FONT_SIZE_BASE,
21 | FONT_SIZE_SM,
22 | FONT_SIZE_LG,
23 | } = constants;
24 |
25 | const _classes = {
26 | fontWeightLight: {fontWeight: FONT_WEIGHT_LIGHT, fontFamily: FONT_FAMILY_BASE_LIGHT},
27 | fontWeightNormal: {fontWeight: FONT_WEIGHT_NORMAL},
28 | fontWeightBold: {fontWeight: FONT_WEIGHT_BOLD, fontFamily: FONT_FAMILY_BASE_BOLD},
29 | fontItalic: {fontStyle: 'italic'},
30 |
31 | textBody: {color: BODY_COLOR},
32 | textWhite: {color: WHITE},
33 | textMuted: {color: TEXT_MUTED},
34 |
35 | textBlack50: {color: Color(BLACK).fade(0.5).rgb().string()},
36 | textWhite50: {color: Color(WHITE).fade(0.5).rgb().string()},
37 |
38 | // textAuto: {textAlign: 'auto'},
39 | // textLeft: {textAlign: 'left'},
40 | // textRight: {textAlign: 'right'},
41 | textCenter: {textAlign: 'center'},
42 | textJustify: {textAlign: 'justify'},
43 |
44 | // experimental
45 | textSmall: {fontSize: FONT_SIZE_SM},
46 | textLarge: {fontSize: FONT_SIZE_LG},
47 | textSpaced: {letterSpacing: FONT_SIZE_BASE * 0.075},
48 |
49 | textMonospace: {fontFamily: FONT_FAMILY_MONOSPACE},
50 | };
51 |
52 | const ALIGN_TYPES = {
53 | 'Auto': 'auto',
54 | 'Left': 'left',
55 | 'Right': 'right',
56 | 'Center': 'center',
57 | 'Justify': 'justify',
58 | };
59 |
60 | // text%value / ex: floatRight
61 | // text%screen%value, / ex: floatLgRight
62 | SCREENS_INFIXES.forEach((itemScreen) => {
63 | Object.keys(ALIGN_TYPES).forEach(item => {
64 | _classes['float' + itemScreen + item] = selectorMediaUp(itemScreen, SCREENS_INFIXES, {
65 | textAlign: ALIGN_TYPES[item],
66 | });
67 | });
68 | });
69 |
70 | // text%color / ex: textPrimary
71 | Object.keys(THEME_COLORS).forEach((item) => {
72 | const classColor = item.charAt(0).toUpperCase() + item.slice(1).toLowerCase();
73 | _classes['text' + classColor] = {color: THEME_COLORS[item]};
74 |
75 | // custom
76 | _classes['text' + classColor + 'Light'] = {color: colorLevel(constants, THEME_COLORS[item], -9)};
77 | _classes['text' + classColor + 'Dark'] = {color: colorLevel(constants, THEME_COLORS[item], 9)};
78 |
79 | // custom / experimental
80 | _classes['text' + classColor + 'Lightest'] = {color: colorLevel(constants, THEME_COLORS[item], -11)};
81 | _classes['text' + classColor + 'Darkest'] = {color: colorLevel(constants, THEME_COLORS[item], -11)};
82 | });
83 | // RESERVED / a#color%item: @include hover-focus { color: darken($color, 10%) !important; } // MIXIN_TEXT_EMPHASIS_VARIANT
84 |
85 | // @mixin text-emphasis-variant($parent, $color) {
86 | // #{$parent} {
87 | // color: $color !important;
88 | // }
89 | // a#{$parent} {
90 | // @include hover-focus {
91 | // color: darken($color, 10%) !important;
92 | // }
93 | // }
94 | // }
95 |
96 | return _classes;
97 | };
98 |
--------------------------------------------------------------------------------
/src/mixins/selectors.js:
--------------------------------------------------------------------------------
1 | // selectors accept raw loop param(s) or booleans
2 | // TODO: how about returning FALSE, instead of empty dict?
3 |
4 | export const selectorFirstChild = (indexOrBool, style = {}) => (
5 | typeof indexOrBool === 'boolean' ? (
6 | indexOrBool ? style : {}
7 | ) : (
8 | indexOrBool == 0 ? style : {}
9 | )
10 | );
11 |
12 | export const selectorLastChild = (indexOrBool, lengthOrStyle = {}, style = {}) => (
13 | arguments.length < 3 ? (
14 | indexOrBool ? style : {}
15 | ) : (
16 | typeof indexOrBool === 'boolean' ? (
17 | indexOrBool ? style : {}
18 | ) : (
19 | indexOrBool == lengthOrStyle - 1 ? style : {}
20 | )
21 | )
22 | );
23 |
24 | export const selectorNotFirstChild = (indexOrBool, style = {}) => (
25 | typeof indexOrBool === 'boolean' ? (
26 | indexOrBool ? style : {}
27 | ) : (
28 | indexOrBool > 0 ? style : {}
29 | )
30 | );
31 |
32 | export const selectorNotLastChild = (indexOrBool, lengthOrStyle, style = {}) => (
33 | arguments.length < 3 ? (
34 | indexOrBool ? style : {}
35 | ) : (
36 | typeof indexOrBool === 'boolean' ? (
37 | indexOrBool ? style : {}
38 | ) : (
39 | indexOrBool < lengthOrStyle - 1 ? style : {}
40 | )
41 | )
42 | );
43 |
44 | export const selectorPreviousChild = (indexOrBool, lengthOrStyle = {}, style = {}) => (
45 | arguments.length < 3 ? (
46 | indexOrBool ? lengthOrStyle : {}
47 | ) : (
48 | typeof indexOrBool === 'boolean' ? (
49 | indexOrBool ? style : {}
50 | ) : (
51 | indexOrBool < lengthOrStyle - 1 ? style : {}
52 | )
53 | )
54 | );
55 |
56 | export const selectorMediaUp = (screen, screens, style = {}) => (
57 | !screen || screens.indexOf(screen) > -1 ? style : false
58 | );
59 |
60 | export const selectorMediaDown = (screen, screens, style = {}) => (
61 | !screen || screens.indexOf(screen) == -1 ? style : false
62 | );
63 |
64 | // RESERVED
65 | // export const selectorCondition = (bool, styleTrue = {}, styleFalse = {}) => (
66 | // bool ? styleTrue : styleFalse
67 | // );
68 |
69 | // OBSOLETED
70 | // bool makes no sense here, in fact
71 | // export const selectorNthChild = (index, condition, style = {}) => (
72 | // condition(index) ? style : {}
73 | // );
74 |
75 | // experimental
76 | export function getSelectors(constants, classes) {
77 |
78 | const {
79 | SCREENS,
80 | GRID_BREAKPOINTS,
81 | ORIENTATION_PORTRAIT,
82 | ORIENTATION_LANDSCAPE,
83 | } = constants;
84 |
85 | const _selectors = {
86 | // pass
87 | };
88 |
89 | // selectorMediaUp%screen, / ex: selectorMediaUpMd
90 | // selectorMediaDown%screen, / ex: selectorMediaDownMd
91 | const SCREENS_INFIXES_ALL = Object.keys(GRID_BREAKPOINTS);
92 |
93 | SCREENS_INFIXES_ALL.forEach((item) => {
94 | _selectors['selectorMediaUp' + item] = (
95 | SCREENS.indexOf(item) > -1 ? style => style : style => {}
96 | );
97 | });
98 |
99 | SCREENS_INFIXES_ALL.forEach((item) => {
100 | _selectors['selectorMediaDown' + item] = (
101 | SCREENS.indexOf(item) == - 1 || SCREENS.indexOf(item) == SCREENS.length - 1 ? style => style : style => {}
102 | );
103 | });
104 |
105 | _selectors['selectorMediaPortrait'] = ORIENTATION_PORTRAIT ? style => style : style => {};
106 | _selectors['selectorMediaLandscape'] = ORIENTATION_LANDSCAPE ? style => style : style => {};
107 |
108 | return {
109 | selectorFirstChild,
110 | selectorLastChild,
111 | selectorNotFirstChild,
112 | selectorPreviousChild,
113 | ..._selectors
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/src/modal.js:
--------------------------------------------------------------------------------
1 | import Color from 'color';
2 |
3 | import { mixinBorderRadius, mixinBorderTopRadius } from './mixins/border-radius';
4 | import { mixinBoxShadow } from './mixins/box-shadow';
5 |
6 | export default function getClasses(constants, classes) {
7 | const {
8 | MODAL_INNER_PADDING,
9 | MODAL_BACKDROP_BG,
10 | MODAL_BACKDROP_OPACITY,
11 | MODAL_DIALOG_MARGIN,
12 | MODAL_TITLE_LINE_HEIGHT,
13 | MODAL_CONTENT_BG,
14 | MODAL_CONTENT_BORDER_WIDTH,
15 | MODAL_CONTENT_BORDER_COLOR,
16 | MODAL_CONTENT_BORDER_RADIUS,
17 | MODAL_CONTENT_SHADOW_COLOR,
18 | MODAL_CONTENT_SHADOW_OFFSET,
19 | MODAL_CONTENT_SHADOW_OPACITY,
20 | MODAL_CONTENT_SHADOW_RADIUS,
21 | MODAL_HEADER_BORDER_COLOR,
22 | MODAL_FOOTER_BORDER_COLOR,
23 | MODAL_HEADER_BORDER_WIDTH,
24 | MODAL_FOOTER_BORDER_WIDTH,
25 | MODAL_HEADER_PADDING_X,
26 | MODAL_HEADER_PADDING_Y,
27 | } = constants;
28 |
29 | const _classes = {
30 | modal: {
31 | backgroundColor: Color(MODAL_BACKDROP_BG).fade(MODAL_BACKDROP_OPACITY).rgb().string(),
32 | flex: 1, // experimental
33 | },
34 |
35 | modalDialog: {
36 | margin: MODAL_DIALOG_MARGIN,
37 | marginTop: MODAL_DIALOG_MARGIN * 3, // custom
38 | flex: 1, // experimental
39 | },
40 |
41 | modalContent: Object.assign({
42 | backgroundColor: MODAL_CONTENT_BG,
43 | borderWidth: MODAL_CONTENT_BORDER_WIDTH,
44 | borderColor: MODAL_CONTENT_BORDER_COLOR,
45 | flex: 1, // experimental
46 | },
47 | mixinBorderRadius(constants, MODAL_CONTENT_BORDER_RADIUS),
48 | mixinBoxShadow(constants, MODAL_CONTENT_SHADOW_COLOR, MODAL_CONTENT_SHADOW_OFFSET, MODAL_CONTENT_SHADOW_OPACITY, MODAL_CONTENT_SHADOW_RADIUS),
49 | ),
50 |
51 | modalHeader: Object.assign({
52 | // display: flex,
53 | alignItems: 'flex-start', // so the close btn always stays on the upper right corner
54 | justifyContent: 'space-between', // Put modal header elements (title and dismiss) on opposite ends
55 | paddingVertical: MODAL_HEADER_PADDING_Y,
56 | paddingHorizontal: MODAL_HEADER_PADDING_X,
57 | borderBottomWidth: MODAL_HEADER_BORDER_WIDTH,
58 | borderBottomColor: MODAL_HEADER_BORDER_COLOR,
59 | borderStyle: 'solid',
60 | },
61 | mixinBorderTopRadius(constants, MODAL_CONTENT_BORDER_RADIUS),
62 | ),
63 |
64 | // experimental
65 | modalHeaderClose: {
66 | position: 'absolute',
67 | right: MODAL_HEADER_PADDING_X,
68 | top: MODAL_HEADER_PADDING_Y,
69 | zIndex: 1,
70 | // RESERVED / padding: $modal-header-padding;
71 | // RESERVED / margin: (-$modal-header-padding) (-$modal-header-padding) (-$modal-header-padding) auto;
72 | },
73 |
74 | modalTitle: {
75 | marginBottom: 0,
76 | lineHeight: MODAL_TITLE_LINE_HEIGHT,
77 | },
78 |
79 | modalBody: {
80 | padding: MODAL_INNER_PADDING,
81 | },
82 |
83 | modalFooter: {
84 | // display: flex,
85 | alignItems: 'center',
86 | justifyContent: 'flex-end', // Right align buttons with flex property because text-align doesn't work on flex items
87 | padding: MODAL_INNER_PADDING,
88 | borderTopWidth: MODAL_FOOTER_BORDER_WIDTH,
89 | borderTopColor: MODAL_FOOTER_BORDER_COLOR,
90 | borderStyle: 'solid',
91 |
92 | // Easily place margin between footer elements
93 | // > :not(:first-child) { margin-left: .25rem; }
94 | // > :not(:last-child) { margin-right: .25rem; }
95 | },
96 | };
97 |
98 | return _classes;
99 | };
100 |
--------------------------------------------------------------------------------
/src/type.js:
--------------------------------------------------------------------------------
1 | import { mixinListUnstyled } from './mixins/lists';
2 |
3 | export default function getClasses(constants, classes) {
4 | const {
5 | SPACER,
6 | H1_FONT_SIZE,
7 | H2_FONT_SIZE,
8 | H3_FONT_SIZE,
9 | H4_FONT_SIZE,
10 | H5_FONT_SIZE,
11 | H6_FONT_SIZE,
12 |
13 | HEADINGS_MARGIN_BOTTOM,
14 | HEADINGS_FONT_FAMILY,
15 | HEADINGS_FONT_WEIGHT,
16 | HEADINGS_COLOR,
17 |
18 | HR_MARGIN_Y,
19 | HR_BORDER_WIDTH,
20 | HR_BORDER_COLOR,
21 | MARK_PADDING, MARK_BG,
22 | BLOCKQUOTE_FONT_SIZE,
23 |
24 | LEAD_FONT_SIZE,
25 | LEAD_FONT_WEIGHT,
26 | } = constants;
27 |
28 | const _classes = {
29 |
30 | hr: {
31 | marginTop: HR_MARGIN_Y,
32 | marginBottom: HR_MARGIN_Y,
33 | borderWidth: 0,
34 | borderTopWidth: HR_BORDER_WIDTH,
35 | borderTopColor: HR_BORDER_COLOR,
36 | borderStyle: 'solid',
37 | },
38 |
39 | // TODO: Could be a selector or not to be at all
40 | // small,
41 | // .small {
42 | // @include font-size($small-font-size);
43 | // font-weight: $font-weight-normal;
44 | // }
45 |
46 | mark: {
47 | padding: MARK_PADDING,
48 | backgroundColor: MARK_BG,
49 | },
50 |
51 | listUnstyled: Object.assign({},
52 | mixinListUnstyled,
53 | ),
54 |
55 | // Inline turns list items into inline-block
56 | // .list-inline {
57 | // @include list-unstyled();
58 | // }
59 | // .list-inline-item {
60 | // display: inline-block;
61 |
62 | // &:not(:last-child) {
63 | // margin-right: $list-inline-padding;
64 | // }
65 | // }
66 |
67 | initialism: {
68 | // reserved / @include font-size(90%),
69 | textTransform: 'uppercase',
70 | },
71 |
72 | blockquote: {
73 | marginBottom: SPACER,
74 | fontSize: BLOCKQUOTE_FONT_SIZE,
75 | },
76 |
77 | // blockquoteFooter {
78 | // display: block;
79 | // @include font-size($blockquote-small-font-size);
80 | // color: $blockquote-small-color;
81 |
82 | // &::before {
83 | // content: "\2014\00A0"; // em dash, nbsp
84 | // }
85 | // },
86 |
87 | lead: {
88 | fontSize: LEAD_FONT_SIZE,
89 | fontWeight: LEAD_FONT_WEIGHT,
90 | },
91 | };
92 |
93 | // h1, h2, h3, ...
94 | const HEADINGS_SIZES = [H1_FONT_SIZE, H2_FONT_SIZE, H3_FONT_SIZE, H4_FONT_SIZE, H5_FONT_SIZE, H6_FONT_SIZE];
95 | ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].forEach((item, index) => {
96 | classes[item] = {
97 | fontSize: HEADINGS_SIZES[index],
98 | marginBottom: HEADINGS_MARGIN_BOTTOM,
99 | fontFamily: HEADINGS_FONT_FAMILY,
100 | fontWeight: HEADINGS_FONT_WEIGHT,
101 | color: HEADINGS_COLOR,
102 | lineHeight: HEADINGS_SIZES[index] * 1.2, // temporal
103 | // RESERVED / lineHeight: HEADINGS_SIZES[index] / FONT_SIZE_BASE * LINE_HEIGHT_BASE,
104 | };
105 | });
106 |
107 | // // Type display classes
108 | // .display-1 {
109 | // font-size: $display1-size;
110 | // font-weight: $display1-weight;
111 | // line-height: $display-line-height;
112 | // }
113 | // .display-2 {
114 | // font-size: $display2-size;
115 | // font-weight: $display2-weight;
116 | // line-height: $display-line-height;
117 | // }
118 | // .display-3 {
119 | // font-size: $display3-size;
120 | // font-weight: $display3-weight;
121 | // line-height: $display-line-height;
122 | // }
123 | // .display-4 {
124 | // font-size: $display4-size;
125 | // font-weight: $display4-weight;
126 | // line-height: $display-line-height;
127 | // }
128 |
129 | return _classes;
130 | };
131 |
--------------------------------------------------------------------------------
/src/pagination.js:
--------------------------------------------------------------------------------
1 | import { mixinPaginationSizePageLink } from './mixins/pagination';
2 | import { mixinBorderRadius, mixinBorderLeftRadius, mixinBorderRightRadius } from './mixins/border-radius';
3 | import { selectorFirstChild, selectorLastChild, selectorCondition } from './mixins/selectors';
4 |
5 | export default function getClasses(constants, classes) {
6 | const {
7 | FONT_SIZE_SM,
8 | FONT_SIZE_LG,
9 | LINE_HEIGHT_SM,
10 | LINE_HEIGHT_LG,
11 | BORDER_RADIUS_SM,
12 | BORDER_RADIUS_LG,
13 | PAGINATION_PADDING_Y, PAGINATION_PADDING_X,
14 | PAGINATION_PADDING_Y_SM, PAGINATION_PADDING_X_SM,
15 | PAGINATION_PADDING_Y_LG, PAGINATION_PADDING_X_LG,
16 | PAGINATION_LINE_HEIGHT,
17 | PAGINATION_COLOR, PAGINATION_BG,
18 | PAGINATION_BORDER_WIDTH, PAGINATION_BORDER_COLOR,
19 | PAGINATION_FOCUS_BOX_SHADOW, PAGINATION_FOCUS_OUTLINE,
20 | PAGINATION_ACTIVE_COLOR,
21 | PAGINATION_ACTIVE_BG,
22 | PAGINATION_ACTIVE_BORDER_COLOR,
23 | PAGINATION_DISABLED_COLOR,
24 | PAGINATION_DISABLED_BG,
25 | PAGINATION_DISABLED_BORDER_COLOR,
26 | } = constants;
27 |
28 | const _classes = {
29 | pagination: Object.assign({
30 | flexDirection: 'row', // TODO: to constant?
31 | },
32 | mixinBorderRadius(constants),
33 | // SKIPPED / @include list-unstyled();
34 | ),
35 |
36 | pageLink: {
37 | position: 'relative',
38 | paddingVertical: PAGINATION_PADDING_Y,
39 | paddingHorizontal: PAGINATION_PADDING_X,
40 | marginLeft: -PAGINATION_BORDER_WIDTH,
41 | lineHeight: PAGINATION_LINE_HEIGHT,
42 | color: PAGINATION_COLOR,
43 | textDecorationLine: 'none', // RFP: any ideas? / if($link-decoration == none, null, none),
44 | backgroundColor: PAGINATION_BG,
45 | borderWidth: PAGINATION_BORDER_WIDTH,
46 | borderColor: PAGINATION_BORDER_COLOR,
47 | borderStyle: 'solid',
48 |
49 | // SKIPPED
50 | // &:hover {
51 | // z-index: 2;
52 | // color: $pagination-hover-color;
53 | // text-decoration: none;
54 | // background-color: $pagination-hover-bg;
55 | // border-color: $pagination-hover-border-color;
56 | // }
57 |
58 | // RESERVED
59 | // &:focus {
60 | // z-index: 3;
61 | // outline: $pagination-focus-outline;
62 | // box-shadow: $pagination-focus-box-shadow;
63 | // }
64 | },
65 |
66 | pageItemFirstChildPageLink: nOrBool => selectorFirstChild(nOrBool, Object.assign({
67 | marginLeft: 0,
68 | },
69 | mixinBorderLeftRadius(constants, BORDER_RADIUS),
70 | )),
71 |
72 | pageItemLastChildPageLink: (nOrBool, lengthOrNone) => selectorLastChild(nOrBool, lengthOrNone, Object.assign({},
73 | mixinBorderRightRadius(constants, BORDER_RADIUS),
74 | )),
75 |
76 | pageItemActivePageLink: e => selectorCondition(e, {
77 | zIndex: 3,
78 | color: PAGINATION_ACTIVE_COLOR,
79 | backgroundColor: PAGINATION_ACTIVE_BG,
80 | borderColor: PAGINATION_ACTIVE_BORDER_COLOR,
81 | }),
82 |
83 | pageItemDisabledPageLink: e => selectorCondition(e, {
84 | color: PAGINATION_DISABLED_COLOR,
85 | backgroundColor: PAGINATION_DISABLED_BG,
86 | borderColor: PAGINATION_DISABLED_BORDER_COLOR,
87 | }),
88 |
89 | // //
90 | // // Sizing
91 | // //
92 |
93 | paginationLg: {
94 | // see paginationLgPageLink, etc
95 | },
96 |
97 | paginationLgPageLink: mixinPaginationSizePageLink(PAGINATION_PADDING_Y_LG, PAGINATION_PADDING_X_LG, FONT_SIZE_LG, LINE_HEIGHT_LG),
98 | paginationLgPageItemFirstChildPageLink: nOrBool => selectorFirstChild(nOrBool, Object.assign({},
99 | mixinBorderLeftRadius(constants, BORDER_RADIUS_LG),
100 | )),
101 | paginationLgPageItemLastChildPageLink: (nOrBool, lengthOrNone) => selectorLastChild(nOrBool, lengthOrNone, Object.assign({},
102 | mixinBorderRightRadius(constants, BORDER_RADIUS_LG),
103 | )),
104 |
105 | paginationSm: {
106 | // see paginationSmPageLink, etc
107 | },
108 |
109 | paginationSmPageLink: mixinPaginationSizePageLink(PAGINATION_PADDING_Y_SM, PAGINATION_PADDING_X_SM, FONT_SIZE_SM, LINE_HEIGHT_SM),
110 | paginationSmPageItemFirstChildPageLink: nOrBool => selectorFirstChild(nOrBool, Object.assign({},
111 | mixinBorderLeftRadius(constants, BORDER_RADIUS_SM),
112 | )),
113 | paginationSmPageItemLastChildPageLink: (nOrBool, lengthOrNone) => selectorLastChild(nOrBool, lengthOrNone, Object.assign({},
114 | mixinBorderRightRadius(constants, BORDER_RADIUS_SM),
115 | )),
116 | };
117 |
118 | return _classes;
119 | };
120 |
--------------------------------------------------------------------------------
/src/button-group.js:
--------------------------------------------------------------------------------
1 | import { mixinBorderLeftRadius, mixinBorderRightRadius } from './mixins/border-radius';
2 | import { mixinBorderTopRadius, mixinBorderBottomRadius } from './mixins/border-radius';
3 | import { selectorNotFirstChild, selectorNotLastChild } from './mixins/selectors';
4 |
5 | export default function getClasses(constants, classes) {
6 | const {
7 | BTN_BORDER_WIDTH,
8 | } = constants;
9 |
10 | const _classes = {
11 |
12 | btnGroup: {
13 | position: 'relative',
14 | // ignored / display: inline-flex,
15 | // ignored /vertical-align: middle; // match .btn alignment given font-size hack above
16 |
17 | // > .btn {
18 | // position: relative;
19 | // flex: 1 1 auto;
20 |
21 | // // Bring the hover, focused, and "active" buttons to the front to overlay
22 | // // the borders properly
23 | // @include hover() {
24 | // z-index: 1;
25 | // }
26 | // &:focus,
27 | // &:active,
28 | // &.active {
29 | // z-index: 1;
30 | // }
31 | // }
32 | },
33 |
34 | btnGroupVertical: {
35 | position: 'relative',
36 | // ignored / display: inline-flex;
37 | // ignored / vertical-align: middle; // match .btn alignment given font-size hack above
38 |
39 | flexDirection: 'column',
40 | // ignored / alignItems: 'flex-start',
41 | // ignored / justifyContent: 'center',
42 |
43 | // > .btn,
44 | // > .btn-group {
45 | // width: 100%;
46 | // }
47 |
48 | // > .btn {
49 | // position: relative;
50 | // flex: 1 1 auto;
51 |
52 | // @include hover() {
53 | // z-index: 1;
54 | // }
55 | // &:focus,
56 | // &:active,
57 | // &.active {
58 | // z-index: 1;
59 | // }
60 | // }
61 | },
62 |
63 | btnToolbar: {
64 | display: 'flex',
65 | flexWrap: 'wrap',
66 | justifyContent: 'flex-start',
67 | },
68 |
69 | // .btn-toolbar {
70 | // .input-group {
71 | // width: auto;
72 | // }
73 | // }
74 |
75 | btnGroupBtn: (n, length) => Object.assign({},
76 | selectorNotFirstChild(n, length, {
77 | marginLeft: -BTN_BORDER_WIDTH,
78 | }),
79 | selectorNotFirstChild(n, mixinBorderLeftRadius(constants, 0)),
80 | selectorNotLastChild(n, length, mixinBorderRightRadius(constants, 0)),
81 | ),
82 |
83 | // ignored / .btn-group-sm > .btn { @extend .btn-sm; }
84 | // ignored / .btn-group-lg > .btn { @extend .btn-lg; }
85 |
86 | // .dropdown-toggle-split {
87 | // padding-right: $btn-padding-x * .75;
88 | // padding-left: $btn-padding-x * .75;
89 |
90 | // &::after,
91 | // .dropup &::after,
92 | // .dropright &::after {
93 | // margin-left: 0;
94 | // }
95 |
96 | // .dropleft &::before {
97 | // margin-right: 0;
98 | // }
99 | // }
100 |
101 | // .btn-sm + .dropdown-toggle-split {
102 | // padding-right: $btn-padding-x-sm * .75;
103 | // padding-left: $btn-padding-x-sm * .75;
104 | // }
105 |
106 | // .btn-lg + .dropdown-toggle-split {
107 | // padding-right: $btn-padding-x-lg * .75;
108 | // padding-left: $btn-padding-x-lg * .75;
109 | // }
110 |
111 | // // The clickable button for toggling the menu
112 | // // Set the same inset shadow as the :active state
113 | // .btn-group.show .dropdown-toggle {
114 | // @include box-shadow($btn-active-box-shadow);
115 |
116 | // // Show no shadow for `.btn-link` since it has no other button styles.
117 | // &.btn-link {
118 | // @include box-shadow(none);
119 | // }
120 | // }
121 |
122 | btnGroupVerticalBtn: (n, length) => Object.assign({},
123 | selectorNotFirstChild(n, length, {
124 | marginTop: -BTN_BORDER_WIDTH,
125 | }),
126 | selectorNotFirstChild(n, mixinBorderTopRadius(constants, 0)),
127 | selectorNotLastChild(n, length, mixinBorderBottomRadius(constants, 0)),
128 | ),
129 |
130 | // // Checkbox and radio options
131 | // //
132 | // // In order to support the browser's form validation feedback, powered by the
133 | // // `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
134 | // // `display: none;` or `visibility: hidden;` as that also hides the popover.
135 | // // Simply visually hiding the inputs via `opacity` would leave them clickable in
136 | // // certain cases which is prevented by using `clip` and `pointer-events`.
137 | // // This way, we ensure a DOM element is visible to position the popover from.
138 | // //
139 | // // See https://github.com/twbs/bootstrap/pull/12794 and
140 | // // https://github.com/twbs/bootstrap/pull/14559 for more information.
141 |
142 | // .btn-group-toggle {
143 | // > .btn,
144 | // > .btn-group > .btn {
145 | // margin-bottom: 0; // Override default `