initial commit?

This commit is contained in:
2019-09-04 23:20:55 +02:00
parent e5950d89ad
commit 80b9a54607
136 changed files with 29510 additions and 29508 deletions

14
.gitignore vendored
View File

@@ -1,7 +1,7 @@
/.project /.project
/settings.php /settings.php
/.buildpath /.buildpath
/.settings/ /.settings/
/style/.sass-cache/ /style/.sass-cache/
/.externalToolBuilders/ /.externalToolBuilders/
/settings.php /settings.php

View File

@@ -1,216 +1,216 @@
<?php <?php
class Auth extends PhpObject class Auth extends PhpObject
{ {
const ALGO = PASSWORD_DEFAULT; const ALGO = PASSWORD_DEFAULT;
const COST = 12; const COST = 12;
const TOKEN_SEP = '|'; const TOKEN_SEP = '|';
const USER_COOKIE_PASS = 'checksum'; const USER_COOKIE_PASS = 'checksum';
const DEFAULT_ERROR = 'Unknown error'; const DEFAULT_ERROR = 'Unknown error';
/** /**
* Database Connection * Database Connection
* @var Db * @var Db
*/ */
private $oDb; private $oDb;
private $iUserId; private $iUserId;
private $sApiKey; private $sApiKey;
public function __construct($oDb, $sApiKey='', $bAutoLogin=true) public function __construct($oDb, $sApiKey='', $bAutoLogin=true)
{ {
parent::__construct(__CLASS__, Settings::DEBUG); parent::__construct(__CLASS__, Settings::DEBUG);
$this->oDb = $oDb; $this->oDb = $oDb;
$this->setUserId(0); $this->setUserId(0);
$this->sApiKey = $sApiKey; $this->sApiKey = $sApiKey;
if($bAutoLogin) $this->autoLogIn(); if($bAutoLogin) $this->autoLogIn();
} }
private function setUserId($iUserId) private function setUserId($iUserId)
{ {
$this->iUserId = $iUserId; $this->iUserId = $iUserId;
} }
public function getUserId() public function getUserId()
{ {
return $this->iUserId; return $this->iUserId;
} }
public function isLoggedIn() public function isLoggedIn()
{ {
return ($this->getUserId() > 0); return ($this->getUserId() > 0);
} }
public function logMeIn($sToken) public function logMeIn($sToken)
{ {
$sDesc = ''; $sDesc = '';
$asUser = $this->getUserFromToken($sToken); $asUser = $this->getUserFromToken($sToken);
if($asUser['success']) if($asUser['success'])
{ {
if(self::checkPassword($asUser['http_pass'], $asUser['pass'])) if(self::checkPassword($asUser['http_pass'], $asUser['pass']))
{ {
$this->setUserId($asUser[Db::getId(MyThoughts::USER_TABLE)]); $this->setUserId($asUser[Db::getId(MyThoughts::USER_TABLE)]);
$this->resetAuthCookie($this->getUserId()); $this->resetAuthCookie($this->getUserId());
} }
else $sDesc = 'wrong password'; else $sDesc = 'wrong password';
} }
else $sDesc = $asUser['desc']; else $sDesc = $asUser['desc'];
return array('success'=>$this->isLoggedIn(), 'desc'=>$sDesc); return array('success'=>$this->isLoggedIn(), 'desc'=>$sDesc);
} }
public function register($sToken, $sNickName, $bLogMeIn=false) public function register($sToken, $sNickName, $bLogMeIn=false)
{ {
$bSuccess = false; $bSuccess = false;
$sDesc = self::DEFAULT_ERROR; $sDesc = self::DEFAULT_ERROR;
$asUser = $this->getUserFromToken($sToken); $asUser = $this->getUserFromToken($sToken);
if(array_key_exists('unknown_user', $asUser)) if(array_key_exists('unknown_user', $asUser))
{ {
$iUserId = $this->addUser($asUser['username'], $sNickName, $asUser['http_pass'], $bLogMeIn); $iUserId = $this->addUser($asUser['username'], $sNickName, $asUser['http_pass'], $bLogMeIn);
if($iUserId > 0) $bSuccess = true; if($iUserId > 0) $bSuccess = true;
else $sDesc = 'Error: Could not add user'; else $sDesc = 'Error: Could not add user';
} }
else $sDesc = 'Someone is already using this nickname, sorry!'; else $sDesc = 'Someone is already using this nickname, sorry!';
$asResult = array('success'=>$bSuccess, 'desc'=>$sDesc); $asResult = array('success'=>$bSuccess, 'desc'=>$sDesc);
return $asResult; return $asResult;
} }
private function getUserFromToken($sToken) private function getUserFromToken($sToken)
{ {
$asResult = array(); $asResult = array();
$bSuccess = false; $bSuccess = false;
$sDesc = self::DEFAULT_ERROR; $sDesc = self::DEFAULT_ERROR;
if($sToken!='') if($sToken!='')
{ {
$asResult['username'] = addslashes(strstr($sToken, self::TOKEN_SEP, true)); $asResult['username'] = addslashes(strstr($sToken, self::TOKEN_SEP, true));
$asResult['http_pass'] = substr(strstr($sToken, self::TOKEN_SEP), strlen(self::TOKEN_SEP)); $asResult['http_pass'] = substr(strstr($sToken, self::TOKEN_SEP), strlen(self::TOKEN_SEP));
if($asResult['username']!='' && $asResult['http_pass']!='') if($asResult['username']!='' && $asResult['http_pass']!='')
{ {
$asUser = $this->oDb->selectRow(MyThoughts::USER_TABLE, array(Db::getText(MyThoughts::USER_TABLE)=>$asResult['username'])); $asUser = $this->oDb->selectRow(MyThoughts::USER_TABLE, array(Db::getText(MyThoughts::USER_TABLE)=>$asResult['username']));
if(!empty($asUser)) if(!empty($asUser))
{ {
$asResult += $asUser; $asResult += $asUser;
$bSuccess = true; $bSuccess = true;
} }
else else
{ {
$asResult['unknown_user'] = true; $asResult['unknown_user'] = true;
$sDesc = 'unknown nickname'; $sDesc = 'unknown nickname';
} }
} }
else $sDesc = 'corrupted token, please login again'; else $sDesc = 'corrupted token, please login again';
} }
else $sDesc = 'no credentials has been received by the server'; else $sDesc = 'no credentials has been received by the server';
$asResult['success'] = $bSuccess; $asResult['success'] = $bSuccess;
$asResult['desc'] = $sDesc; $asResult['desc'] = $sDesc;
return $asResult; return $asResult;
} }
public function autoLogIn() public function autoLogIn()
{ {
if(isset($_COOKIE[self::USER_COOKIE_PASS])) if(isset($_COOKIE[self::USER_COOKIE_PASS]))
{ {
$sCookie = $_COOKIE[self::USER_COOKIE_PASS]; $sCookie = $_COOKIE[self::USER_COOKIE_PASS];
$iUserId = addslashes(strstr($sCookie, self::TOKEN_SEP, true)); $iUserId = addslashes(strstr($sCookie, self::TOKEN_SEP, true));
$sCookie = substr(strstr($sCookie, self::TOKEN_SEP), strlen(self::TOKEN_SEP)); $sCookie = substr(strstr($sCookie, self::TOKEN_SEP), strlen(self::TOKEN_SEP));
$asEmpl = $this->oDb->selectRow(MyThoughts::USER_TABLE, array(Db::getId(MyThoughts::USER_TABLE)=>$iUserId)); $asEmpl = $this->oDb->selectRow(MyThoughts::USER_TABLE, array(Db::getId(MyThoughts::USER_TABLE)=>$iUserId));
if(!empty($asEmpl)) if(!empty($asEmpl))
{ {
if($sCookie==$asEmpl['cookie']) if($sCookie==$asEmpl['cookie'])
{ {
$this->setUserId($asEmpl[Db::getId(MyThoughts::USER_TABLE)]); $this->setUserId($asEmpl[Db::getId(MyThoughts::USER_TABLE)]);
//Reset pass once a day //Reset pass once a day
if(mb_substr($asEmpl['led'], 0, 10) != date('Y-m-d')) $this->resetAuthCookie($this->getUserId()); if(mb_substr($asEmpl['led'], 0, 10) != date('Y-m-d')) $this->resetAuthCookie($this->getUserId());
} }
else $this->addError('token corrompu pour le user '.$asEmpl[Db::getId(MyThoughts::USER_TABLE)]); else $this->addError('token corrompu pour le user '.$asEmpl[Db::getId(MyThoughts::USER_TABLE)]);
} }
else $this->addError('Utilisateur '.$iUserId.' inconnu'); else $this->addError('Utilisateur '.$iUserId.' inconnu');
} }
} }
public function addUser($sUserHash, $sNickName, $sLoginToken, $bLogMeIn=false) public function addUser($sUserHash, $sNickName, $sLoginToken, $bLogMeIn=false)
{ {
$sPass = self::hashPassword($sLoginToken); $sPass = self::hashPassword($sLoginToken);
$bExist = $this->oDb->pingValue(MyThoughts::USER_TABLE, array(Db::getText(MyThoughts::USER_TABLE)=>$sUserHash)); $bExist = $this->oDb->pingValue(MyThoughts::USER_TABLE, array(Db::getText(MyThoughts::USER_TABLE)=>$sUserHash));
if($bExist) return -1; if($bExist) return -1;
else else
{ {
$iUserId = $this->oDb->insertRow(MyThoughts::USER_TABLE, array(Db::getText(MyThoughts::USER_TABLE)=>$sUserHash, 'nickname'=>$sNickName, 'pass'=>$sPass)); $iUserId = $this->oDb->insertRow(MyThoughts::USER_TABLE, array(Db::getText(MyThoughts::USER_TABLE)=>$sUserHash, 'nickname'=>$sNickName, 'pass'=>$sPass));
if($iUserId>0 && $bLogMeIn) if($iUserId>0 && $bLogMeIn)
{ {
$this->logMeIn($sUserHash.self::TOKEN_SEP.$sPass); $this->logMeIn($sUserHash.self::TOKEN_SEP.$sPass);
} }
} }
return $iUserId; return $iUserId;
} }
//TODO integrate with logMeIn() //TODO integrate with logMeIn()
public function checkApiKey($sApiKey) public function checkApiKey($sApiKey)
{ {
return ($this->sApiKey!='' && $sApiKey==$this->sApiKey); return ($this->sApiKey!='' && $sApiKey==$this->sApiKey);
} }
private function resetPass($iUserId=0) private function resetPass($iUserId=0)
{ {
$sUserIdCol = Db::getId(MyThoughts::USER_TABLE); $sUserIdCol = Db::getId(MyThoughts::USER_TABLE);
$sUserTextCol = Db::getText(MyThoughts::USER_TABLE); $sUserTextCol = Db::getText(MyThoughts::USER_TABLE);
$asInfo = array('select'=>array($sUserIdCol, $sUserTextCol), 'from'=>MyThoughts::USER_TABLE); $asInfo = array('select'=>array($sUserIdCol, $sUserTextCol), 'from'=>MyThoughts::USER_TABLE);
if($iUserId>0) $asInfo['constraint'] = array($sUserIdCol=>$iUserId); if($iUserId>0) $asInfo['constraint'] = array($sUserIdCol=>$iUserId);
$asUsers = $this->oDb->selectRows($asInfo); $asUsers = $this->oDb->selectRows($asInfo);
foreach($asUsers as $asUser) foreach($asUsers as $asUser)
{ {
$sToken = self::hashPassword(self::getLoginToken($asUser[$sUserTextCol])); $sToken = self::hashPassword(self::getLoginToken($asUser[$sUserTextCol]));
$this->oDb->updateRow(MyThoughts::USER_TABLE, array(Db::getId(MyThoughts::USER_TABLE)=>$asUser[$sUserIdCol]), array('pass'=>$sToken)); $this->oDb->updateRow(MyThoughts::USER_TABLE, array(Db::getId(MyThoughts::USER_TABLE)=>$asUser[$sUserIdCol]), array('pass'=>$sToken));
} }
} }
public static function getLoginToken($sPass) public static function getLoginToken($sPass)
{ {
//Add Server Name //Add Server Name
$sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD']; $sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD'];
$sAppPath = $_SERVER['REQUEST_SCHEME'].'://'.str_replace(array('http://', 'https://'), '', $sServerName.dirname($_SERVER['SCRIPT_NAME'])); $sAppPath = $_SERVER['REQUEST_SCHEME'].'://'.str_replace(array('http://', 'https://'), '', $sServerName.dirname($_SERVER['SCRIPT_NAME']));
$_GET['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':''); $_GET['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':'');
return md5($sPass.$_GET['serv_name']); return md5($sPass.$_GET['serv_name']);
} }
private function resetAuthCookie($iUserId) private function resetAuthCookie($iUserId)
{ {
$sNewPass = self::getAuthCookie($iUserId); $sNewPass = self::getAuthCookie($iUserId);
$iTimeLimit = time() + 60 * 60 * 24 * 30; $iTimeLimit = time() + 60 * 60 * 24 * 30;
$this->oDb->updateRow(MyThoughts::USER_TABLE, array(Db::getId(MyThoughts::USER_TABLE)=>$iUserId), array("cookie"=>$sNewPass)); $this->oDb->updateRow(MyThoughts::USER_TABLE, array(Db::getId(MyThoughts::USER_TABLE)=>$iUserId), array("cookie"=>$sNewPass));
setcookie(self::USER_COOKIE_PASS, $iUserId.self::TOKEN_SEP.$sNewPass, $iTimeLimit); setcookie(self::USER_COOKIE_PASS, $iUserId.self::TOKEN_SEP.$sNewPass, $iTimeLimit);
} }
private static function getAuthCookie() private static function getAuthCookie()
{ {
return self::hashPassword return self::hashPassword
( (
$_SERVER['HTTP_USER_AGENT']. $_SERVER['HTTP_USER_AGENT'].
$_SERVER['REMOTE_ADDR']. $_SERVER['REMOTE_ADDR'].
$_SERVER['REQUEST_TIME']. $_SERVER['REQUEST_TIME'].
mb_strstr(microtime(), ' ', true). mb_strstr(microtime(), ' ', true).
$_SERVER['SERVER_SIGNATURE']. $_SERVER['SERVER_SIGNATURE'].
$_SERVER['SERVER_ADMIN'] $_SERVER['SERVER_ADMIN']
); );
} }
private static function hashPassword($sPass) private static function hashPassword($sPass)
{ {
return password_hash($sPass, self::ALGO, array('cost'=>self::COST)); return password_hash($sPass, self::ALGO, array('cost'=>self::COST));
} }
private static function checkPassword($sPass, $sHash) private static function checkPassword($sPass, $sHash)
{ {
return password_verify($sPass, $sHash); return password_verify($sPass, $sHash);
} }
} }
?> ?>

View File

@@ -1,142 +1,142 @@
<?php <?php
class Calendar extends PhpObject class Calendar extends PhpObject
{ {
const CAL_YEAR = 'cy'; const CAL_YEAR = 'cy';
const CAL_MONTH = 'cm'; const CAL_MONTH = 'cm';
private $oMySql; private $oMySql;
private $oSession; private $oSession;
private $oMask; private $oMask;
private $iUserId; private $iUserId;
private $iYear; private $iYear;
private $iMonth; private $iMonth;
function __construct($oMySql, $oSession) function __construct($oMySql, $oSession)
{ {
parent::__construct(); parent::__construct();
$this->oMySql = $oMySql; $this->oMySql = $oMySql;
$this->oSession = $oSession; $this->oSession = $oSession;
$this->oMask = new Mask('calendar'); $this->oMask = new Mask('calendar');
$this->iYear = 0; $this->iYear = 0;
$this->iMonth = 0; $this->iMonth = 0;
} }
public function setDate($iYear=0, $iMonth=0) public function setDate($iYear=0, $iMonth=0)
{ {
if($iYear==0) if($iYear==0)
{ {
$iYear = date('Y'); $iYear = date('Y');
} }
if($iMonth==0) if($iMonth==0)
{ {
$iMonth = date('m'); $iMonth = date('m');
} }
$this->iYear = $iYear; $this->iYear = $iYear;
$this->iMonth = $iMonth; $this->iMonth = $iMonth;
} }
private function getThoughts() private function getThoughts()
{ {
//TODO essayer avec selectRows //TODO essayer avec selectRows
$sQuery = "SELECT DATE_FORMAT(led, '%d') AS day $sQuery = "SELECT DATE_FORMAT(led, '%d') AS day
FROM ".Db::THOUGHTS_TABLE." FROM ".Db::THOUGHTS_TABLE."
WHERE ".Db::getId(Db::USERS_TABLE)." = ".$this->oSession->getUserId()." WHERE ".Db::getId(Db::USERS_TABLE)." = ".$this->oSession->getUserId()."
AND YEAR(led) = ".$this->iYear." AND YEAR(led) = ".$this->iYear."
AND MONTH(led) = ".$this->iMonth." AND MONTH(led) = ".$this->iMonth."
GROUP BY day GROUP BY day
ORDER BY day"; ORDER BY day";
return $this->oMySql->getArrayQuery($sQuery, true); return $this->oMySql->getArrayQuery($sQuery, true);
} }
private function getUpdatedLink($asParams) private function getUpdatedLink($asParams)
{ {
$sCurrentVariables = $_SERVER['QUERY_STRING']; $sCurrentVariables = $_SERVER['QUERY_STRING'];
$asCurrentVariables = explode('&', $sCurrentVariables); $asCurrentVariables = explode('&', $sCurrentVariables);
foreach($asCurrentVariables as $sParam) foreach($asCurrentVariables as $sParam)
{ {
$sKey = strstr($sParam, '=', true); $sKey = strstr($sParam, '=', true);
$sValue = substr(strstr($sParam, '='), 1); $sValue = substr(strstr($sParam, '='), 1);
$asVariables[$sKey] = $sValue; $asVariables[$sKey] = $sValue;
} }
return '?'.implodeAll(array_merge($asVariables, $asParams), '=', '&'); return '?'.implodeAll(array_merge($asVariables, $asParams), '=', '&');
} }
private function getLink($iOffset) private function getLink($iOffset)
{ {
$iTimeStamp = mktime(0, 0, 0, $this->iMonth + $iOffset, 1, $this->iYear); $iTimeStamp = mktime(0, 0, 0, $this->iMonth + $iOffset, 1, $this->iYear);
return $this->getUpdatedLink(array(self::CAL_MONTH=>date('n', $iTimeStamp), self::CAL_YEAR=>date('Y', $iTimeStamp))); return $this->getUpdatedLink(array(self::CAL_MONTH=>date('n', $iTimeStamp), self::CAL_YEAR=>date('Y', $iTimeStamp)));
} }
private function setMaskItems() private function setMaskItems()
{ {
//week starting on the sunday : offset = 0, monday : offset = 1 //week starting on the sunday : offset = 0, monday : offset = 1
$iOffset = 1; $iOffset = 1;
//days in the month //days in the month
$iMonthLastDay = date('d', mktime(0, 0, 0, $this->iMonth+1, 0, $this->iYear)); $iMonthLastDay = date('d', mktime(0, 0, 0, $this->iMonth+1, 0, $this->iYear));
$asDays = range(1, $iMonthLastDay); $asDays = range(1, $iMonthLastDay);
$iDayNb = 1 - date($iOffset?'N':'w', mktime(0, 0, 0, $this->iMonth, 1, $this->iYear)) + $iOffset; $iDayNb = 1 - date($iOffset?'N':'w', mktime(0, 0, 0, $this->iMonth, 1, $this->iYear)) + $iOffset;
$iCalendarLastDay = $iMonthLastDay + (7 - date($iOffset?'N':'w', mktime(0, 0, 0, $this->iMonth+1, 0, $this->iYear))) + $iOffset; $iCalendarLastDay = $iMonthLastDay + (7 - date($iOffset?'N':'w', mktime(0, 0, 0, $this->iMonth+1, 0, $this->iYear))) + $iOffset;
//days with thoughts //days with thoughts
$asThoughts = $this->getThoughts(); $asThoughts = $this->getThoughts();
while($iDayNb < $iCalendarLastDay) while($iDayNb < $iCalendarLastDay)
{ {
$iCurrentDayTimeStamp = mktime(0, 0, 0, $this->iMonth, $iDayNb, $this->iYear); $iCurrentDayTimeStamp = mktime(0, 0, 0, $this->iMonth, $iDayNb, $this->iYear);
$sItemDate = date('d', $iCurrentDayTimeStamp); $sItemDate = date('d', $iCurrentDayTimeStamp);
//new week //new week
if(date('w', $iCurrentDayTimeStamp) == $iOffset) if(date('w', $iCurrentDayTimeStamp) == $iOffset)
{ {
$this->oMask->newInstance('WEEK'); $this->oMask->newInstance('WEEK');
} }
//day within month //day within month
if(date('n', $iCurrentDayTimeStamp)==$this->iMonth) if(date('n', $iCurrentDayTimeStamp)==$this->iMonth)
{ {
$bThoughts = in_array($iDayNb, $asThoughts); $bThoughts = in_array($iDayNb, $asThoughts);
$sItemClass = $bThoughts?'full':'empty'; $sItemClass = $bThoughts?'full':'empty';
$sItemLink = $bThoughts?$this->getUpdatedLink(array('d'=>date(MyThoughts::URL_DATE_FORMAT, $iCurrentDayTimeStamp), 'p'=>'r')):'#'; $sItemLink = $bThoughts?$this->getUpdatedLink(array('d'=>date(MyThoughts::URL_DATE_FORMAT, $iCurrentDayTimeStamp), 'p'=>'r')):'#';
$sItemLinkTitle = $bThoughts?'See my thoughts on '.date(MyThoughts::LAYOUT_DATE_FORMAT, $iCurrentDayTimeStamp):''; $sItemLinkTitle = $bThoughts?'See my thoughts on '.date(MyThoughts::LAYOUT_DATE_FORMAT, $iCurrentDayTimeStamp):'';
} }
else else
{ {
$sItemClass = 'disabled'; $sItemClass = 'disabled';
$sItemLink = '#'; $sItemLink = '#';
$sItemLinkTitle = ''; $sItemLinkTitle = '';
} }
$this->oMask->addInstance('DAY', array('item_day'=>$sItemDate, 'item_class'=>$sItemClass, 'item_link'=>$sItemLink, 'item_link_title'=>$sItemLinkTitle)); $this->oMask->addInstance('DAY', array('item_day'=>$sItemDate, 'item_class'=>$sItemClass, 'item_link'=>$sItemLink, 'item_link_title'=>$sItemLinkTitle));
$iDayNb++; $iDayNb++;
} }
//column titles //column titles
$asDayNames = array('1'=>'Mon', '2'=>'Tue', '3'=>'Wed', '4'=>'Thu', '5'=>'Fri', '6'=>'Sat', $iOffset?'7':'0'=>'Sun'); $asDayNames = array('1'=>'Mon', '2'=>'Tue', '3'=>'Wed', '4'=>'Thu', '5'=>'Fri', '6'=>'Sat', $iOffset?'7':'0'=>'Sun');
ksort($asDayNames); ksort($asDayNames);
foreach($asDayNames as $sDayName) foreach($asDayNames as $sDayName)
{ {
$this->oMask->addInstance('TITLE', array('day_name'=>$sDayName)); $this->oMask->addInstance('TITLE', array('day_name'=>$sDayName));
} }
} }
public function getCalendar() public function getCalendar()
{ {
$sResult = ''; $sResult = '';
if($this->iYear!=0 && $this->iMonth!=0) if($this->iYear!=0 && $this->iMonth!=0)
{ {
$this->oMask->setTag('link_prev', $this->getLink(-1)); $this->oMask->setTag('link_prev', $this->getLink(-1));
$this->oMask->setTag('current_month', date('F', mktime(0, 0, 0, $this->iMonth, 1, $this->iYear))); $this->oMask->setTag('current_month', date('F', mktime(0, 0, 0, $this->iMonth, 1, $this->iYear)));
$this->oMask->setTag('link_next', $this->getLink(1)); $this->oMask->setTag('link_next', $this->getLink(1));
$this->setMaskItems(); $this->setMaskItems();
$sResult = $this->oMask->getMask(); $sResult = $this->oMask->getMask();
} }
return $sResult; return $sResult;
} }
} }
?> ?>

View File

@@ -1,242 +1,242 @@
<?php <?php
/** /**
* Main Class * Main Class
* @author franzz * @author franzz
* @version 2.0 * @version 2.0
*/ */
class MyThoughts extends Main class MyThoughts extends Main
{ {
//Interface keywords //Interface keywords
const SUCCESS = 'success'; const SUCCESS = 'success';
const ERROR = 'error'; const ERROR = 'error';
const UNAUTHORIZED = 'unauthorized'; const UNAUTHORIZED = 'unauthorized';
const NOT_FOUND = 'unknown action'; const NOT_FOUND = 'unknown action';
//SQL tables //SQL tables
const USER_TABLE = 'users'; const USER_TABLE = 'users';
const SETTINGS_TABLE = 'settings'; const SETTINGS_TABLE = 'settings';
//Mythoughts //Mythoughts
const URL_DATE_FORMAT = 'Ymd'; const URL_DATE_FORMAT = 'Ymd';
const LAYOUT_DATE_FORMAT = 'F \t\h\e jS, Y'; const LAYOUT_DATE_FORMAT = 'F \t\h\e jS, Y';
const MYSQL_DATE_FORMAT = 'Y-m-d'; const MYSQL_DATE_FORMAT = 'Y-m-d';
const LAYOUT_TIME_FORMAT = 'G:i'; const LAYOUT_TIME_FORMAT = 'G:i';
const WELCOME_MSG_FILE = 'welcome'; const WELCOME_MSG_FILE = 'welcome';
const SETTING_LAYOUT = 'layout'; const SETTING_LAYOUT = 'layout';
const LAYOUT_ONE_PAGE = '1'; const LAYOUT_ONE_PAGE = '1';
const LAYOUT_TWO_PAGES = '2'; const LAYOUT_TWO_PAGES = '2';
const SETTING_FONT = 'font'; const SETTING_FONT = 'font';
const FONT_THOUGHTS = 'thoughts'; const FONT_THOUGHTS = 'thoughts';
const FONT_ARIAL = 'Arial'; const FONT_ARIAL = 'Arial';
const FONT_VERDANA = 'Verdana'; const FONT_VERDANA = 'Verdana';
const SETTING_SIZE = 'Size'; const SETTING_SIZE = 'Size';
const SIZE_16 = '16'; const SIZE_16 = '16';
const SIZE_18 = '18'; const SIZE_18 = '18';
const SIZE_20 = '20'; const SIZE_20 = '20';
const LAST_THOUGHT_LIMIT = 60*60*24; const LAST_THOUGHT_LIMIT = 60*60*24;
//Format //Format
const OBJ = 'object'; const OBJ = 'object';
const ARRAY = 'array'; const ARRAY = 'array';
const JSON = 'json'; const JSON = 'json';
/** /**
* Auth Object * Auth Object
* @var Auth * @var Auth
*/ */
private $oAuth; private $oAuth;
/** /**
* Main constructor [to be called from index.php] * Main constructor [to be called from index.php]
* @param ClassManagement $oClassManagement * @param ClassManagement $oClassManagement
* @param string $sLang * @param string $sLang
*/ */
public function __construct($oClassManagement, $sProcessPage) public function __construct($oClassManagement, $sProcessPage)
{ {
//Load classes //Load classes
//$this->oClassManagement->incClass('calendar', true); //$this->oClassManagement->incClass('calendar', true);
$asClasses = array( array('name'=>'auth', 'project'=>true), $asClasses = array( array('name'=>'auth', 'project'=>true),
array('name'=>'thought', 'project'=>true)); array('name'=>'thought', 'project'=>true));
parent::__construct($oClassManagement, $sProcessPage, $asClasses); parent::__construct($oClassManagement, $sProcessPage, $asClasses);
//Init objects //Init objects
if($this->oDb->sDbState == Db::DB_PEACHY) $this->oAuth = new Auth($this->oDb, Settings::API_KEY); if($this->oDb->sDbState == Db::DB_PEACHY) $this->oAuth = new Auth($this->oDb, Settings::API_KEY);
} }
protected function install() protected function install()
{ {
$this->oAuth = new Auth($this->oDb, Settings::API_KEY, false); $this->oAuth = new Auth($this->oDb, Settings::API_KEY, false);
//Install DB //Install DB
$this->oDb->install(); $this->oDb->install();
} }
private function setContext($sProcessPage) private function setContext($sProcessPage)
{ {
//Browser <> PHP <> MySql synchronization //Browser <> PHP <> MySql synchronization
date_default_timezone_set(Settings::TIMEZONE); date_default_timezone_set(Settings::TIMEZONE);
ini_set('default_charset', Settings::TEXT_ENC); ini_set('default_charset', Settings::TEXT_ENC);
header('Content-Type: text/html; charset='.Settings::TEXT_ENC); header('Content-Type: text/html; charset='.Settings::TEXT_ENC);
mb_internal_encoding(Settings::TEXT_ENC); mb_internal_encoding(Settings::TEXT_ENC);
mb_http_output(Settings::TEXT_ENC); mb_http_output(Settings::TEXT_ENC);
mb_http_input(Settings::TEXT_ENC); mb_http_input(Settings::TEXT_ENC);
mb_language('uni'); mb_language('uni');
mb_regex_encoding(Settings::TEXT_ENC); mb_regex_encoding(Settings::TEXT_ENC);
$this->asContext['process_page'] = basename($sProcessPage); $this->asContext['process_page'] = basename($sProcessPage);
$sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD']; $sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD'];
$sAppPath = 'http://'.str_replace('http://', '', $sServerName.dirname($_SERVER['SCRIPT_NAME'])); $sAppPath = 'http://'.str_replace('http://', '', $sServerName.dirname($_SERVER['SCRIPT_NAME']));
$this->asContext['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':''); $this->asContext['serv_name'] = $sAppPath.(mb_substr($sAppPath, -1)!='/'?'/':'');
} }
public function addUncaughtError($sError) public function addUncaughtError($sError)
{ {
$this->addError('Uncaught errors:'."\n".$sError); $this->addError('Uncaught errors:'."\n".$sError);
} }
/* Authorizations handling */ /* Authorizations handling */
public function register($sToken, $sNickname) public function register($sToken, $sNickname)
{ {
$asResult = $this->oAuth->register($sToken, $sNickname); $asResult = $this->oAuth->register($sToken, $sNickname);
if($asResult['success']) return $this->logMeIn($sToken); if($asResult['success']) return $this->logMeIn($sToken);
else return self::getJsonResult($asResult['success'], $asResult['desc']); else return self::getJsonResult($asResult['success'], $asResult['desc']);
} }
public function isLoggedIn() public function isLoggedIn()
{ {
return $this->oAuth->isLoggedIn(); return $this->oAuth->isLoggedIn();
} }
public function logMeIn($sToken) public function logMeIn($sToken)
{ {
$asLogResult = $this->oAuth->logMeIn($sToken); $asLogResult = $this->oAuth->logMeIn($sToken);
return MyThoughts::getJsonResult($asLogResult['success'], $asLogResult['desc'], $this->getVars()); return MyThoughts::getJsonResult($asLogResult['success'], $asLogResult['desc'], $this->getVars());
} }
public function checkApiKey($sApiKey) public function checkApiKey($sApiKey)
{ {
return $this->oAuth->checkApiKey($sApiKey); return $this->oAuth->checkApiKey($sApiKey);
} }
/* Building main pages */ /* Building main pages */
public function getPage() public function getPage()
{ {
//Constants //Constants
$asGlobalVars = array( $asGlobalVars = array(
'consts' => array( 'consts' => array(
'token_sep' => Auth::TOKEN_SEP, 'token_sep' => Auth::TOKEN_SEP,
'error' => self::ERROR, 'error' => self::ERROR,
'success' => self::SUCCESS, 'success' => self::SUCCESS,
'context' => $this->asContext, 'context' => $this->asContext,
'cookie' => Auth::USER_COOKIE_PASS 'cookie' => Auth::USER_COOKIE_PASS
), ),
'vars' => $this->getVars() 'vars' => $this->getVars()
); );
//Pages //Pages
$asPages = array('logon', 'logoff', 'write', 'read', 'settings', 'template', 'editor'); $asPages = array('logon', 'logoff', 'write', 'read', 'settings', 'template', 'editor');
foreach($asPages as $sPage) $asGlobalVars['consts']['pages'][$sPage] = $this->getPageContent($sPage); foreach($asPages as $sPage) $asGlobalVars['consts']['pages'][$sPage] = $this->getPageContent($sPage);
//Main Page //Main Page
$sPage = $this->getPageContent('index'); $sPage = $this->getPageContent('index');
$sPage = str_replace('asGlobalVars', json_encode($asGlobalVars), $sPage); $sPage = str_replace('asGlobalVars', json_encode($asGlobalVars), $sPage);
return $sPage; return $sPage;
} }
private function getVars() { private function getVars() {
return array( return array(
'id' => $this->oAuth->getUserId(), 'id' => $this->oAuth->getUserId(),
'log_in' => $this->isLoggedIn() 'log_in' => $this->isLoggedIn()
); );
} }
/* DB structure. See Db::__construct */ /* DB structure. See Db::__construct */
protected function getSqlOptions() protected function getSqlOptions()
{ {
return array( return array(
'tables' => array( 'tables' => array(
self::USER_TABLE => array(Db::getText(self::USER_TABLE), 'nickname', 'pass', 'cookie'), self::USER_TABLE => array(Db::getText(self::USER_TABLE), 'nickname', 'pass', 'cookie'),
Thought::THOUGHT_TABLE => array(Db::getId(self::USER_TABLE), Db::getText(Thought::THOUGHT_TABLE), 'created'), Thought::THOUGHT_TABLE => array(Db::getId(self::USER_TABLE), Db::getText(Thought::THOUGHT_TABLE), 'created'),
self::SETTINGS_TABLE => array(Db::getId(self::USER_TABLE), Db::getText(self::SETTINGS_TABLE), 'value') self::SETTINGS_TABLE => array(Db::getId(self::USER_TABLE), Db::getText(self::SETTINGS_TABLE), 'value')
), ),
'types' => array( 'types' => array(
Db::getText(self::USER_TABLE) => "varchar(32) NOT NULL", Db::getText(self::USER_TABLE) => "varchar(32) NOT NULL",
'nickname' => "varchar(60) NOT NULL", 'nickname' => "varchar(60) NOT NULL",
'pass' => "varchar(256) NOT NULL", 'pass' => "varchar(256) NOT NULL",
'cookie' => "varchar(255)", 'cookie' => "varchar(255)",
Db::getText(Thought::THOUGHT_TABLE) => "longtext", Db::getText(Thought::THOUGHT_TABLE) => "longtext",
'created' => "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP", 'created' => "timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP",
Db::getText(self::SETTINGS_TABLE) => "varchar(20) NOT NULL", Db::getText(self::SETTINGS_TABLE) => "varchar(20) NOT NULL",
'value' => "varchar(20) NOT NULL" 'value' => "varchar(20) NOT NULL"
), ),
'constraints' => array( 'constraints' => array(
self::USER_TABLE => "UNIQUE KEY `unique_username` (`".Db::getText(self::USER_TABLE)."`)" self::USER_TABLE => "UNIQUE KEY `unique_username` (`".Db::getText(self::USER_TABLE)."`)"
), ),
'cascading_delete' => array( 'cascading_delete' => array(
self::USER_TABLE => array(self::SETTINGS_TABLE, Thought::THOUGHT_TABLE) self::USER_TABLE => array(self::SETTINGS_TABLE, Thought::THOUGHT_TABLE)
) )
); );
} }
/* Thoughts */ /* Thoughts */
public function getThought($iThoughtId, $sFormat=self::OBJ) public function getThought($iThoughtId, $sFormat=self::OBJ)
{ {
$oThought = new Thought($this->oDb, $this->oAuth->getUserId()); $oThought = new Thought($this->oDb, $this->oAuth->getUserId());
if($iThoughtId=='last') $oThought->openLast(self::LAST_THOUGHT_LIMIT); if($iThoughtId=='last') $oThought->openLast(self::LAST_THOUGHT_LIMIT);
else $oThought->open($iThoughtId); else $oThought->open($iThoughtId);
switch($sFormat) switch($sFormat)
{ {
case self::OBJ: case self::OBJ:
return $oThought; break; return $oThought; break;
case self::ARRAY: case self::ARRAY:
return $oThought->get(); break; return $oThought->get(); break;
case self::JSON: case self::JSON:
return self::getJsonResult(true, '', $oThought->get()); break; return self::getJsonResult(true, '', $oThought->get()); break;
} }
} }
public function updateThought($asOps, $iThoughtId=0) public function updateThought($asOps, $iThoughtId=0)
{ {
$oThought = new Thought($this->oDb, $this->oAuth->getUserId(), $iThoughtId); $oThought = new Thought($this->oDb, $this->oAuth->getUserId(), $iThoughtId);
$oThought->setOps($asOps); $oThought->setOps($asOps);
$iThoughtId = $oThought->save(); $iThoughtId = $oThought->save();
$bSuccess = ($iThoughtId>0); $bSuccess = ($iThoughtId>0);
$sDesc = 'thought '.($bSuccess?'':'not ').'saved'; $sDesc = 'thought '.($bSuccess?'':'not ').'saved';
return self::getJsonResult($bSuccess, $sDesc, $this->getThought($iThoughtId, self::ARRAY)); return self::getJsonResult($bSuccess, $sDesc, $this->getThought($iThoughtId, self::ARRAY));
} }
public function getThoughtDates() public function getThoughtDates()
{ {
$asThoughts = Thought::getThoughtDates($this->oDb, $this->oAuth->getUserId()); $asThoughts = Thought::getThoughtDates($this->oDb, $this->oAuth->getUserId());
foreach($asThoughts as &$asThought) $asThought['created_f'] = self::formatDate($asThought['created'], 'j M'); foreach($asThoughts as &$asThought) $asThought['created_f'] = self::formatDate($asThought['created'], 'j M');
return self::getJsonResult(true, '', $asThoughts); return self::getJsonResult(true, '', $asThoughts);
} }
/* Static toolbox functions */ /* Static toolbox functions */
public static function getSafeNickName($sNickName) public static function getSafeNickName($sNickName)
{ {
return $sNickName; return $sNickName;
} }
private static function formatDate($iTime, $sFormat, $sField='') private static function formatDate($iTime, $sFormat, $sField='')
{ {
$iTime = ($sField == '')?$iTime:$iTime[$sField]; $iTime = ($sField == '')?$iTime:$iTime[$sField];
$iTime = is_numeric($iTime)?$iTime:strtotime($iTime); $iTime = is_numeric($iTime)?$iTime:strtotime($iTime);
return date($sFormat, $iTime); return date($sFormat, $iTime);
} }
} }
?> ?>

View File

@@ -1,103 +1,103 @@
<?php <?php
class Setting extends PhpObject { class Setting extends PhpObject {
const SETTING_LAYOUT = 'layout'; const SETTING_LAYOUT = 'layout';
const LAYOUT_ONE_PAGE = '1'; const LAYOUT_ONE_PAGE = '1';
const LAYOUT_TWO_PAGES = '2'; const LAYOUT_TWO_PAGES = '2';
const SETTING_FONT = 'font'; const SETTING_FONT = 'font';
const FONT_THOUGHTS = 'thoughts'; const FONT_THOUGHTS = 'thoughts';
const FONT_ARIAL = 'Arial'; const FONT_ARIAL = 'Arial';
const FONT_VERDANA = 'Verdana'; const FONT_VERDANA = 'Verdana';
const SETTING_SIZE = 'Size'; const SETTING_SIZE = 'Size';
const SIZE_16 = '16'; const SIZE_16 = '16';
const SIZE_18 = '18'; const SIZE_18 = '18';
const SIZE_20 = '20'; const SIZE_20 = '20';
/** /**
* Database Handle * Database Handle
* @var Db * @var Db
*/ */
private $oDb; private $oDb;
public function __construct(&$oDb) public function __construct(&$oDb)
{ {
parent::__construct(__CLASS__, Settings::DEBUG); parent::__construct(__CLASS__, Settings::DEBUG);
$this->oDb = $oDb; $this->oDb = $oDb;
} }
public static function getSettingsList() public static function getSettingsList()
{ {
//TODO Save on database (param table) //TODO Save on database (param table)
return array(self::SETTING_FONT, self::SETTING_SIZE, self::SETTING_LAYOUT); return array(self::SETTING_FONT, self::SETTING_SIZE, self::SETTING_LAYOUT);
} }
private static function getDefaultSetting($sSettingName) private static function getDefaultSetting($sSettingName)
{ {
switch($sSettingName) switch($sSettingName)
{ {
case self::SETTING_FONT: case self::SETTING_FONT:
return self::FONT_THOUGHTS; return self::FONT_THOUGHTS;
case self::SETTING_LAYOUT: case self::SETTING_LAYOUT:
return self::LAYOUT_ONE_PAGE; return self::LAYOUT_ONE_PAGE;
} }
return false; return false;
} }
private function getSetting($sSettingName) private function getSetting($sSettingName)
{ {
if(!array_key_exists($sSettingName, $this->asSettings)) if(!array_key_exists($sSettingName, $this->asSettings))
{ {
$asConstraint = array(Db::getText(Db::SETTINGS_TABLE)=>$sSettingName, Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId()); $asConstraint = array(Db::getText(Db::SETTINGS_TABLE)=>$sSettingName, Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId());
$oValue = $this->oMySql->selectValue(Db::SETTINGS_TABLE, 'value', $asConstraint); $oValue = $this->oMySql->selectValue(Db::SETTINGS_TABLE, 'value', $asConstraint);
$this->asSettings[$sSettingName] = (!$oValue)?self::getDefaultSetting($sSettingName):$oValue; $this->asSettings[$sSettingName] = (!$oValue)?self::getDefaultSetting($sSettingName):$oValue;
} }
return $this->asSettings[$sSettingName]; return $this->asSettings[$sSettingName];
} }
private function setSetting($sValue, $sSettingName) private function setSetting($sValue, $sSettingName)
{ {
$this->oMySql->insertUpdateRow(Db::SETTINGS_TABLE, array('setting'=>$sSettingName, Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId()), array('value'=>$sValue)); $this->oMySql->insertUpdateRow(Db::SETTINGS_TABLE, array('setting'=>$sSettingName, Db::getId(Db::USERS_TABLE)=>$this->oSession->getUserId()), array('value'=>$sValue));
} }
public function setSettings($asSettings) public function setSettings($asSettings)
{ {
array_walk($asSettings, array($this, 'setSetting')); array_walk($asSettings, array($this, 'setSetting'));
} }
public function settingsPage() public function settingsPage()
{ {
$this->setPage('settings'); $this->setPage('settings');
$this->setPageTitle('Settings'); $this->setPageTitle('Settings');
$asSettingsOptions = array( self::SETTING_LAYOUT => array( $asSettingsOptions = array( self::SETTING_LAYOUT => array(
'One extensible page' => self::LAYOUT_ONE_PAGE, 'One extensible page' => self::LAYOUT_ONE_PAGE,
'Two Pages, Diary like' => self::LAYOUT_TWO_PAGES), 'Two Pages, Diary like' => self::LAYOUT_TWO_PAGES),
self::SETTING_FONT => array( self::SETTING_FONT => array(
'AES Crawl' => self::FONT_THOUGHTS, 'AES Crawl' => self::FONT_THOUGHTS,
'Arial' => self::FONT_ARIAL, 'Arial' => self::FONT_ARIAL,
'Verdana' => self::FONT_VERDANA), 'Verdana' => self::FONT_VERDANA),
self::SETTING_SIZE => array( self::SETTING_SIZE => array(
'16pt' => self::SIZE_16, '16pt' => self::SIZE_16,
'18pt' => self::SIZE_18, '18pt' => self::SIZE_18,
'20pt' => self::SIZE_20)); '20pt' => self::SIZE_20));
foreach(self::getSettingsList() as $sSettingName) foreach(self::getSettingsList() as $sSettingName)
{ {
$this->oPageMask->newInstance('SETTING'); $this->oPageMask->newInstance('SETTING');
$this->oPageMask->setInstanceTag('SETTING', 'setting_name', $sSettingName); $this->oPageMask->setInstanceTag('SETTING', 'setting_name', $sSettingName);
$sUserSetting = $this->getSetting($sSettingName); $sUserSetting = $this->getSetting($sSettingName);
foreach($asSettingsOptions[$sSettingName] as $sOptionName=>$sOptionValue) foreach($asSettingsOptions[$sSettingName] as $sOptionName=>$sOptionValue)
{ {
if($sOptionValue == self::getDefaultSetting($sSettingName)) if($sOptionValue == self::getDefaultSetting($sSettingName))
{ {
$sOptionName .= ' (Default)'; $sOptionName .= ' (Default)';
} }
$sSelectedOption = ($sUserSetting==$sOptionValue)?'selected':''; $sSelectedOption = ($sUserSetting==$sOptionValue)?'selected':'';
$asSettingOptions = array( 'setting_option_value'=>$sOptionValue, $asSettingOptions = array( 'setting_option_value'=>$sOptionValue,
'setting_option_selected'=>$sSelectedOption, 'setting_option_selected'=>$sSelectedOption,
'setting_option_name'=>$sOptionName); 'setting_option_name'=>$sOptionName);
$this->oPageMask->addInstance('SETTING_OPTION', $asSettingOptions); $this->oPageMask->addInstance('SETTING_OPTION', $asSettingOptions);
} }
} }
} }
} }

View File

@@ -1,136 +1,136 @@
<?php <?php
class Thought extends PhpObject class Thought extends PhpObject
{ {
const THOUGHT_TABLE = 'thoughts'; const THOUGHT_TABLE = 'thoughts';
private $iId; private $iId;
private $iUserId; private $iUserId;
private $asOps; private $asOps;
private $iCreateTimestamp; private $iCreateTimestamp;
private $sLed; private $sLed;
/** /**
* Database Handle * Database Handle
* @var Db * @var Db
*/ */
private $oDb; private $oDb;
public function __construct(&$oDb, $iUserId, $iId=0) public function __construct(&$oDb, $iUserId, $iId=0)
{ {
parent::__construct(__CLASS__, Settings::DEBUG); parent::__construct(__CLASS__, Settings::DEBUG);
$this->oDb = $oDb; $this->oDb = $oDb;
$this->setUserId($iUserId); $this->setUserId($iUserId);
$this->setId($iId); $this->setId($iId);
} }
public function getId() public function getId()
{ {
return $this->iId; return $this->iId;
} }
public function setId($iId, $bOpen=true) public function setId($iId, $bOpen=true)
{ {
$this->iId = $iId; $this->iId = $iId;
if($this->iId > 0 && $bOpen) $this->open($this->iId); if($this->iId > 0 && $bOpen) $this->open($this->iId);
} }
private function setUserId($iUserId) private function setUserId($iUserId)
{ {
$this->iUserId = $iUserId; $this->iUserId = $iUserId;
} }
public function setOps($asOps, $bSave=false) public function setOps($asOps, $bSave=false)
{ {
$this->asOps = $asOps; $this->asOps = $asOps;
if($bSave) return $this->save(); if($bSave) return $this->save();
} }
public function openLast($iLimit=0) public function openLast($iLimit=0)
{ {
$iId = $this->oDb->selectValue( $iId = $this->oDb->selectValue(
self::THOUGHT_TABLE, self::THOUGHT_TABLE,
"MAX(".Db::getId(self::THOUGHT_TABLE).")", "MAX(".Db::getId(self::THOUGHT_TABLE).")",
array(Db::getId(MyThoughts::USER_TABLE) => $this->iUserId)); array(Db::getId(MyThoughts::USER_TABLE) => $this->iUserId));
$bSuccess = ($iId > 0); $bSuccess = ($iId > 0);
if($bSuccess) $this->open($iId); if($bSuccess) $this->open($iId);
return $bSuccess; return $bSuccess;
} }
public function open($iId) public function open($iId)
{ {
if($iId > 0) if($iId > 0)
{ {
if($this->iUserId > 0) { if($this->iUserId > 0) {
$asWhere = array(Db::getId(self::THOUGHT_TABLE)=>$iId, Db::getId(MyThoughts::USER_TABLE) => $this->iUserId); $asWhere = array(Db::getId(self::THOUGHT_TABLE)=>$iId, Db::getId(MyThoughts::USER_TABLE) => $this->iUserId);
$asInfo = $this->oDb->selectRow(self::THOUGHT_TABLE, $asWhere); $asInfo = $this->oDb->selectRow(self::THOUGHT_TABLE, $asWhere);
$this->iId = $asInfo[Db::getId(self::THOUGHT_TABLE)]; $this->iId = $asInfo[Db::getId(self::THOUGHT_TABLE)];
$this->iUserId = $asInfo[Db::getId(MyThoughts::USER_TABLE)]; $this->iUserId = $asInfo[Db::getId(MyThoughts::USER_TABLE)];
$this->asOps = self::decodeThought($asInfo[Db::getText(self::THOUGHT_TABLE)]); $this->asOps = self::decodeThought($asInfo[Db::getText(self::THOUGHT_TABLE)]);
$this->iCreateTimestamp = strtotime($asInfo['created']); $this->iCreateTimestamp = strtotime($asInfo['created']);
$this->sLed = $asInfo['led']; $this->sLed = $asInfo['led'];
} }
else $this->addError('getting thought info with no user id'); else $this->addError('getting thought info with no user id');
} }
else $this->addError('getting thought info with no thought id'); else $this->addError('getting thought info with no thought id');
} }
public function save() public function save()
{ {
$asThought = array( $asThought = array(
Db::getId(MyThoughts::USER_TABLE) => $this->iUserId, Db::getId(MyThoughts::USER_TABLE) => $this->iUserId,
Db::getText(self::THOUGHT_TABLE) => self::encodeThought($this->asOps) Db::getText(self::THOUGHT_TABLE) => self::encodeThought($this->asOps)
); );
if($this->iId > 0) $this->oDb->updateRow(self::THOUGHT_TABLE, $this->iId, $asThought); if($this->iId > 0) $this->oDb->updateRow(self::THOUGHT_TABLE, $this->iId, $asThought);
else $this->iId = $this->oDb->insertRow(self::THOUGHT_TABLE, $asThought); else $this->iId = $this->oDb->insertRow(self::THOUGHT_TABLE, $asThought);
return $this->iId; return $this->iId;
} }
public function get() public function get()
{ {
return array( return array(
'id' => $this->iId, 'id' => $this->iId,
'id_user' => $this->iUserId, 'id_user' => $this->iUserId,
'ops' => $this->asOps, 'ops' => $this->asOps,
'created' => $this->iCreateTimestamp, 'created' => $this->iCreateTimestamp,
'created_f' => date('l, j F', $this->iCreateTimestamp), 'created_f' => date('l, j F', $this->iCreateTimestamp),
'led' => $this->sLed 'led' => $this->sLed
); );
} }
public static function getThoughtDates(Db $oDb, int $iUser) public static function getThoughtDates(Db $oDb, int $iUser)
{ {
$asInfo = array( $asInfo = array(
'select' => array(Db::getId(self::THOUGHT_TABLE), 'created'), 'select' => array(Db::getId(self::THOUGHT_TABLE), 'created'),
'from' => self::THOUGHT_TABLE, 'from' => self::THOUGHT_TABLE,
'constraint'=> array(Db::getId(MyThoughts::USER_TABLE) => $iUser), 'constraint'=> array(Db::getId(MyThoughts::USER_TABLE) => $iUser),
'orderBy' => array('created'=>'DESC') 'orderBy' => array('created'=>'DESC')
); );
return $oDb->selectRows($asInfo); return $oDb->selectRows($asInfo);
} }
private static function encodeThought($sthought) private static function encodeThought($sthought)
{ {
return base64_encode(serialize(explode("\n", self::shuffleText(json_encode($sthought))))); return base64_encode(serialize(explode("\n", self::shuffleText(json_encode($sthought)))));
} }
private static function decodeThought($sEncodedThought) private static function decodeThought($sEncodedThought)
{ {
return json_decode(self::shuffleText(implode("\n", unserialize(base64_decode($sEncodedThought)))), true); return json_decode(self::shuffleText(implode("\n", unserialize(base64_decode($sEncodedThought)))), true);
} }
private static function shuffleText($sText) private static function shuffleText($sText)
{ {
$sRandomText = Settings::RAND_TEXT; $sRandomText = Settings::RAND_TEXT;
for($iIndex=0; $iIndex < strlen($sText); $iIndex++) for($iIndex=0; $iIndex < strlen($sText); $iIndex++)
{ {
$sText[$iIndex] = $sRandomText[$iIndex%strlen($sRandomText)] ^ $sText[$iIndex]; $sText[$iIndex] = $sRandomText[$iIndex%strlen($sRandomText)] ^ $sText[$iIndex];
} }
return $sText; return $sText;
} }
} }

390
index.php
View File

@@ -1,196 +1,196 @@
<?php <?php
/* /*
MyThoughts Project MyThoughts Project
http://git.lutran.fr/main.git http://git.lutran.fr/main.git
Copyright (C) 2015 François Lutran Copyright (C) 2015 François Lutran
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses along with this program. If not, see http://www.gnu.org/licenses
*/ */
/* Requests Handler */ /* Requests Handler */
//Start buffering //Start buffering
ob_start(); ob_start();
require_once '../objects/class_management.php'; require_once '../objects/class_management.php';
$oClassManagement = new ClassManagement('mythoughts'); $oClassManagement = new ClassManagement('mythoughts');
ToolBox::cleanPost($_POST); ToolBox::cleanPost($_POST);
ToolBox::cleanPost($_GET); ToolBox::cleanPost($_GET);
ToolBox::cleanPost($_REQUEST); ToolBox::cleanPost($_REQUEST);
ToolBox::fixGlobalVars(isset($argv)?$argv:array()); ToolBox::fixGlobalVars(isset($argv)?$argv:array());
//Available variables //Available variables
$sToken = isset($_REQUEST['token'])?$_REQUEST['token']:''; $sToken = isset($_REQUEST['token'])?$_REQUEST['token']:'';
$sAction = isset($_REQUEST['a'])?$_REQUEST['a']:''; $sAction = isset($_REQUEST['a'])?$_REQUEST['a']:'';
$sPage = isset($_GET['p'])?$_GET['p']:'index'; $sPage = isset($_GET['p'])?$_GET['p']:'index';
$sNickName = isset($_REQUEST['nickname'])?$_REQUEST['nickname']:''; $sNickName = isset($_REQUEST['nickname'])?$_REQUEST['nickname']:'';
$iApiKey = isset($_GET['api'])?$_GET['api']:''; $iApiKey = isset($_GET['api'])?$_GET['api']:'';
$sContent = isset($_POST['content'])?$_POST['content']:''; $sContent = isset($_POST['content'])?$_POST['content']:'';
$iId = isset($_REQUEST['id'])?$_REQUEST['id']:0; $iId = isset($_REQUEST['id'])?$_REQUEST['id']:0;
//Initiate class //Initiate class
$oMyThoughts = new MyThoughts($oClassManagement, __FILE__); $oMyThoughts = new MyThoughts($oClassManagement, __FILE__);
$bLoggedIn = $oMyThoughts->isLoggedIn(); $bLoggedIn = $oMyThoughts->isLoggedIn();
$sResult = ''; $sResult = '';
if($sAction=='logmein') $sResult = $oMyThoughts->logMeIn($sToken); if($sAction=='logmein') $sResult = $oMyThoughts->logMeIn($sToken);
elseif($sAction!='' && $bLoggedIn) elseif($sAction!='' && $bLoggedIn)
{ {
switch ($sAction) switch ($sAction)
{ {
case 'load': case 'load':
$sResult = $oMyThoughts->getThought($iId, MyThoughts::JSON); $sResult = $oMyThoughts->getThought($iId, MyThoughts::JSON);
break; break;
case 'update': case 'update':
$sResult = $oMyThoughts->updateThought($sContent, $iId); $sResult = $oMyThoughts->updateThought($sContent, $iId);
break; break;
case 'thoughts': case 'thoughts':
$sResult = $oMyThoughts->getThoughtDates(); $sResult = $oMyThoughts->getThoughtDates();
break; break;
default: default:
$sResult = MyThoughts::getJsonResult(false, MyThoughts::NOT_FOUND); $sResult = MyThoughts::getJsonResult(false, MyThoughts::NOT_FOUND);
} }
} }
elseif($sAction!='' && !$bLoggedIn) elseif($sAction!='' && !$bLoggedIn)
{ {
if($oMyThoughts->checkApiKey($iApiKey)) if($oMyThoughts->checkApiKey($iApiKey))
{ {
switch ($sAction) switch ($sAction)
{ {
case '': case '':
//$sResult = $oMyThoughts->apifunction(); //$sResult = $oMyThoughts->apifunction();
break; break;
default: default:
$sResult = MyThoughts::getJsonResult(false, MyThoughts::NOT_FOUND); $sResult = MyThoughts::getJsonResult(false, MyThoughts::NOT_FOUND);
} }
} }
elseif($sAction=='register') $sResult = $oMyThoughts->register($sToken, $sNickName); elseif($sAction=='register') $sResult = $oMyThoughts->register($sToken, $sNickName);
else $sResult = MyThoughts::getJsonResult(false, MyThoughts::UNAUTHORIZED); else $sResult = MyThoughts::getJsonResult(false, MyThoughts::UNAUTHORIZED);
} }
else $sResult = $oMyThoughts->getPage(); else $sResult = $oMyThoughts->getPage();
$sDebug = ob_get_clean(); $sDebug = ob_get_clean();
if(Settings::DEBUG && $sDebug!='') $oMyThoughts->addUncaughtError($sDebug); if(Settings::DEBUG && $sDebug!='') $oMyThoughts->addUncaughtError($sDebug);
echo $sResult; echo $sResult;
/* /*
//load classes //load classes
session_start(); session_start();
require_once 'config.php'; require_once 'config.php';
//clean sent values //clean sent values
cleanPost($_POST); cleanPost($_POST);
cleanPost($_GET); cleanPost($_GET);
cleanPost($_REQUEST); cleanPost($_REQUEST);
//general //general
$sPage = (isset($_GET['p']) && $_GET['p']!='')?$_GET['p']:'w'; $sPage = (isset($_GET['p']) && $_GET['p']!='')?$_GET['p']:'w';
$sPostToken = isset($_POST['post_token'])?$_POST['post_token']:''; $sPostToken = isset($_POST['post_token'])?$_POST['post_token']:'';
//logon //logon
$sLogin = (isset($_POST['login']) && $_POST['login']!='Nickname')?$_POST['login']:''; $sLogin = (isset($_POST['login']) && $_POST['login']!='Nickname')?$_POST['login']:'';
$sPass = (isset($_POST['pass']) && $_POST['pass']!='Password')?$_POST['pass']:''; $sPass = (isset($_POST['pass']) && $_POST['pass']!='Password')?$_POST['pass']:'';
$bRegister = (isset($_POST['register']) && $_POST['register']==1); $bRegister = (isset($_POST['register']) && $_POST['register']==1);
//writing pad //writing pad
$sThought = isset($_POST['thoughts'])?$_POST['thoughts']:''; $sThought = isset($_POST['thoughts'])?$_POST['thoughts']:'';
$iThoughtId = (isset($_POST['thought_id']) && $_POST['thought_id']!='')?$_POST['thought_id']:0; //update or insert $iThoughtId = (isset($_POST['thought_id']) && $_POST['thought_id']!='')?$_POST['thought_id']:0; //update or insert
$bFinishedWriting = isset($_POST['finished']); $bFinishedWriting = isset($_POST['finished']);
//calendar //calendar
$iDay = isset($_GET['d'])?$_GET['d']:date(MyThoughts::URL_DATE_FORMAT); //d = yyyymmdd $iDay = isset($_GET['d'])?$_GET['d']:date(MyThoughts::URL_DATE_FORMAT); //d = yyyymmdd
$iCalYear = isset($_GET[Calendar::CAL_YEAR])?$_GET[Calendar::CAL_YEAR]:0; //cy = yyyy $iCalYear = isset($_GET[Calendar::CAL_YEAR])?$_GET[Calendar::CAL_YEAR]:0; //cy = yyyy
$iCalMonth = isset($_GET[Calendar::CAL_MONTH])?$_GET[Calendar::CAL_MONTH]:0; //cm = m $iCalMonth = isset($_GET[Calendar::CAL_MONTH])?$_GET[Calendar::CAL_MONTH]:0; //cm = m
$oMyThougths = new MyThoughts(); $oMyThougths = new MyThoughts();
$bValidPost = ($sPostToken!='' && $oMyThougths->checkPostToken($sPostToken)); $bValidPost = ($sPostToken!='' && $oMyThougths->checkPostToken($sPostToken));
if($bValidPost) if($bValidPost)
{ {
if($bRegister) if($bRegister)
{ {
$oMyThougths->register($sLogin, $sPass); $oMyThougths->register($sLogin, $sPass);
$sPage = 'r'; $sPage = 'r';
} }
elseif($sLogin!='' && $sPass!='') elseif($sLogin!='' && $sPass!='')
{ {
$oMyThougths->logMeIn($sLogin, $sPass); $oMyThougths->logMeIn($sLogin, $sPass);
} }
} }
//if loggued in //if loggued in
if(!$oMyThougths->isLogguedIn()) if(!$oMyThougths->isLogguedIn())
{ {
$oMyThougths->logonPage($sLogin); $oMyThougths->logonPage($sLogin);
} }
else else
{ {
$oMyThougths->activateMenu(); $oMyThougths->activateMenu();
$oMyThougths->setCalendarDate(); $oMyThougths->setCalendarDate();
switch($sPage) switch($sPage)
{ {
case 'w': //write a thought case 'w': //write a thought
if($bValidPost && $sThought!='' && $sThought!='Talk to me.') if($bValidPost && $sThought!='' && $sThought!='Talk to me.')
{ {
if($iThoughtId==0) if($iThoughtId==0)
{ {
$iThoughtId = $oMyThougths->addThought($sThought); $iThoughtId = $oMyThougths->addThought($sThought);
} }
else else
{ {
$oMyThougths->updateThought($iThoughtId, $sThought); $oMyThougths->updateThought($iThoughtId, $sThought);
} }
} }
if($bFinishedWriting) if($bFinishedWriting)
{ {
$oMyThougths->readingPage(); $oMyThougths->readingPage();
} }
else else
{ {
$oMyThougths->writingPage($iThoughtId); $oMyThougths->writingPage($iThoughtId);
} }
break; break;
case 'r': //read a thought (per day) case 'r': //read a thought (per day)
if($iDay<=0 || !$oMyThougths->readingPage(strtotime($iDay))) if($iDay<=0 || !$oMyThougths->readingPage(strtotime($iDay)))
{ {
$oMyThougths->writingPage(); $oMyThougths->writingPage();
} }
break; break;
case 's': // go to settings page case 's': // go to settings page
if($bValidPost) if($bValidPost)
{ {
$asSettings = array_intersect_key($_POST, array_flip($oMyThougths->getSettingsList())); $asSettings = array_intersect_key($_POST, array_flip($oMyThougths->getSettingsList()));
$oMyThougths->setSettings($asSettings); $oMyThougths->setSettings($asSettings);
$oMyThougths->writingPage(); $oMyThougths->writingPage();
} }
else else
{ {
$oMyThougths->settingsPage(); $oMyThougths->settingsPage();
} }
break; break;
case 'q': //quit case 'q': //quit
$oMyThougths->logMeOut(); $oMyThougths->logMeOut();
} }
if($iCalYear!=0 && $iCalMonth!=0) if($iCalYear!=0 && $iCalMonth!=0)
{ {
$oMyThougths->setCalendarDate($iCalYear, $iCalMonth); $oMyThougths->setCalendarDate($iCalYear, $iCalMonth);
} }
} }
echo $oMyThougths->getPage(); echo $oMyThougths->getPage();
*/ */
?> ?>

View File

@@ -1,11 +1,11 @@
<div class="edi_header"></div> <div class="edi_header"></div>
<div class="edi_container"> <div class="edi_container">
<div class="edi_content"> <div class="edi_content">
<div class="edi_table" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></div> <div class="edi_table" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"></div>
</div> </div>
</div> </div>
<div class="edi_nav"> <div class="edi_nav">
<div class="nav-elem prev"><a class="fal fa-fw fa-prev"></a></div> <div class="nav-elem prev"><a class="fal fa-fw fa-prev"></a></div>
<div class="nav-elem curr"></div> <div class="nav-elem curr"></div>
<div class="nav-elem next"><a class="fal fa-fw fa-next"></a></div> <div class="nav-elem next"><a class="fal fa-fw fa-next"></a></div>
</div> </div>

View File

@@ -1,23 +1,23 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" /> <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<meta name="author" content="Franzz" /> <meta name="author" content="Franzz" />
<link href="style/mythoughts.css" rel="stylesheet" type="text/css" /> <link href="style/mythoughts.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="scripts/jquery.min.js"></script> <script type="text/javascript" src="scripts/jquery.min.js"></script>
<script type="text/javascript" src="scripts/bootstrap.bundle.min.js"></script> <script type="text/javascript" src="scripts/bootstrap.bundle.min.js"></script>
<script type="text/javascript" src="scripts/jquery.mousewheel.min.js"></script> <script type="text/javascript" src="scripts/jquery.mousewheel.min.js"></script>
<script type="text/javascript" src="scripts/quill.min.js"></script> <script type="text/javascript" src="scripts/quill.min.js"></script>
<script type="text/javascript" src="scripts/common.js"></script> <script type="text/javascript" src="scripts/common.js"></script>
<script type="text/javascript" src="scripts/mythoughts.js"></script> <script type="text/javascript" src="scripts/mythoughts.js"></script>
<link rel="shortcut icon" href="images/favicon2.ico" /> <link rel="shortcut icon" href="images/favicon2.ico" />
<title>My Thoughts</title> <title>My Thoughts</title>
<script type="text/javascript"> <script type="text/javascript">
var oMyThoughts = new MyThoughts(asGlobalVars); var oMyThoughts = new MyThoughts(asGlobalVars);
$(document).ready(oMyThoughts.init); $(document).ready(oMyThoughts.init);
</script> </script>
</head> </head>
<body> <body>
<div id="container"></div> <div id="container"></div>
</body> </body>
</html> </html>

View File

@@ -1,8 +1,8 @@
<div id="logoff">Bye...</div> <div id="logoff">Bye...</div>
<script type="text/javascript"> <script type="text/javascript">
oMyThoughts.pageInit = function(asHash, bFirstPage) oMyThoughts.pageInit = function(asHash, bFirstPage)
{ {
document.cookie = self.consts.cookie+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC"; document.cookie = self.consts.cookie+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC";
location.href = self.consts.root; location.href = self.consts.root;
}; };
</script> </script>

View File

@@ -1,96 +1,96 @@
<div id="logon" class="border border-grey-400 shadow rounded"> <div id="logon" class="border border-grey-400 shadow rounded">
<form name="post_logon" id="post_logon" method="post"> <form name="post_logon" id="post_logon" method="post">
<div class="form-group align-items-center"> <div class="form-group align-items-center">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text" data-toggle="tooltip" data-placement="left" title="Username"><i class="fal fa-user"></i></span> <span class="input-group-text" data-toggle="tooltip" data-placement="left" title="Username"><i class="fal fa-user"></i></span>
</div> </div>
<input type="text" class="form-control" placeholder="Nickname" name="login" id="login" tool value="Franzz" /> <input type="text" class="form-control" placeholder="Nickname" name="login" id="login" tool value="Franzz" />
</div> </div>
</div> </div>
<div class="form-group align-items-center"> <div class="form-group align-items-center">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text" data-toggle="tooltip" data-placement="left" title="Password"><i class="fal fa-password"></i></span> <span class="input-group-text" data-toggle="tooltip" data-placement="left" title="Password"><i class="fal fa-password"></i></span>
</div> </div>
<input type="password" class="form-control" placeholder="Password" name="pass" id="pass" value="123456" /> <input type="password" class="form-control" placeholder="Password" name="pass" id="pass" value="123456" />
</div> </div>
</div> </div>
<div id="pass_conf_box" class="form-group align-items-center collapse"> <div id="pass_conf_box" class="form-group align-items-center collapse">
<div class="input-group"> <div class="input-group">
<div class="input-group-prepend"> <div class="input-group-prepend">
<span class="input-group-text" data-toggle="tooltip" data-placement="left" title="Repeat password"> <span class="input-group-text" data-toggle="tooltip" data-placement="left" title="Repeat password">
<i class="fal fa-password first"></i> <i class="fal fa-password first"></i>
<i class="fal fa-password second"></i> <i class="fal fa-password second"></i>
</span> </span>
</div> </div>
<input type="password" class="form-control" placeholder="Confirm password" name="pass_conf" id="pass_conf" value="123456" /> <input type="password" class="form-control" placeholder="Confirm password" name="pass_conf" id="pass_conf" value="123456" />
</div> </div>
</div> </div>
<div id="btn_box" class="btn-toolbar justify-content-between" role="toolbar"> <div id="btn_box" class="btn-toolbar justify-content-between" role="toolbar">
<button type="button" class="btn btn-secondary shadow-sm transition" id="register">Register</button> <button type="button" class="btn btn-secondary shadow-sm transition" id="register">Register</button>
<button type="button" class="btn btn-primary shadow-sm" name="signin" id="signin">Sign in</button> <button type="button" class="btn btn-primary shadow-sm" name="signin" id="signin">Sign in</button>
</div> </div>
</form> </form>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
oMyThoughts.pageInit = function(asHash, bFirstPage) oMyThoughts.pageInit = function(asHash, bFirstPage)
{ {
self.elem.$Main.addClass('no_frame'); self.elem.$Main.addClass('no_frame');
$('[data-toggle="tooltip"]').tooltip(); $('[data-toggle="tooltip"]').tooltip();
//$(window).keyup(function(e){if(e.which==13) logMeIn();}); //$(window).keyup(function(e){if(e.which==13) logMeIn();});
$('#signin').click(logMeIn); $('#signin').click(logMeIn);
$('#register').on('click submit', function(event){ $('#register').on('click submit', function(event){
event.preventDefault(); event.preventDefault();
$(this) $(this)
.blur() .blur()
.off('click') .off('click')
.click(register); .click(register);
$('#pass_conf_box').collapse('show'); $('#pass_conf_box').collapse('show');
$('#signin').hide('fast', function(){$('#btn_box').addClass('registering');}); $('#signin').hide('fast', function(){$('#btn_box').addClass('registering');});
}); });
}; };
function logMeIn() function logMeIn()
{ {
var oChecker = $('#post_logon').checkForm('#login, #pass'); var oChecker = $('#post_logon').checkForm('#login, #pass');
if(oChecker.success) if(oChecker.success)
{ {
var asInputs = getInputs(); var asInputs = getInputs();
Tools.ajax( Tools.ajax(
'logmein', 'logmein',
oMyThoughts.loadHome, oMyThoughts.loadHome,
{token: getToken(asInputs)}, {token: getToken(asInputs)},
); );
} }
else Tools.feedback('warning', oChecker.desc); else Tools.feedback('warning', oChecker.desc);
} }
function register() function register()
{ {
var oChecker = $('#post_logon').checkForm(); var oChecker = $('#post_logon').checkForm();
if(oChecker.success) if(oChecker.success)
{ {
var asInputs = getInputs(); var asInputs = getInputs();
Tools.ajax( Tools.ajax(
'register', 'register',
oMyThoughts.loadHome, oMyThoughts.loadHome,
{token: getToken(asInputs), nickname:asInputs.nickname} {token: getToken(asInputs), nickname:asInputs.nickname}
); );
} }
else Tools.feedback('warning', oChecker.desc); else Tools.feedback('warning', oChecker.desc);
} }
function getInputs() { function getInputs() {
var sNickname = $('#login').val(); var sNickname = $('#login').val();
var sUsername = sNickname.toLowerCase().replace(/\s+/g, ''); var sUsername = sNickname.toLowerCase().replace(/\s+/g, '');
var sPass = $.trim($('#pass').val()); var sPass = $.trim($('#pass').val());
return {username: sUsername, nickname: sNickname, pass: sPass}; return {username: sUsername, nickname: sNickname, pass: sPass};
} }
function getToken(asInputs) { function getToken(asInputs) {
return md5(asInputs.username)+oMyThoughts.consts.token_sep+getLoginToken(asInputs.pass); return md5(asInputs.username)+oMyThoughts.consts.token_sep+getLoginToken(asInputs.pass);
} }
</script> </script>

View File

@@ -1,13 +1,13 @@
<div id="read"></div> <div id="read"></div>
<script type="text/javascript"> <script type="text/javascript">
oMyThoughts.pageInit = function(asHash, bFirstPage) { oMyThoughts.pageInit = function(asHash, bFirstPage) {
oEditor = new Editor('#read', true); oEditor = new Editor('#read', true);
oEditor.open(asHash.items[0]); oEditor.open(asHash.items[0]);
}; };
oMyThoughts.onSamePageMove = function(asHash) { oMyThoughts.onSamePageMove = function(asHash) {
$('#read').empty(); $('#read').empty();
self.pageInit(self.getHash()); self.pageInit(self.getHash());
return false; return false;
}; };
</script> </script>

View File

@@ -1,17 +1,17 @@
<div id="feedback"></div> <div id="feedback"></div>
<div id="header"></div> <div id="header"></div>
<div id="menu"> <div id="menu">
<ul> <ul>
<li><a href="#settings" class="button fal fa-settings"></a></li> <li><a href="#settings" class="button fal fa-settings"></a></li>
<li><a href="#logoff" class="button fal fa-logoff"></a></li> <li><a href="#logoff" class="button fal fa-logoff"></a></li>
</ul> </ul>
</div> </div>
<div id="main"></div> <div id="main"></div>
<div id="side"> <div id="side">
<div class="tag write"><a href="#write" class="fal fa-write"></a></div> <div class="tag write"><a href="#write" class="fal fa-write"></a></div>
</div> </div>
<footer> <footer>
<span>Designed and powered by Franzz &amp; Clarita. </span> <span>Designed and powered by Franzz &amp; Clarita. </span>
<span>My Thoughts Project under <a href="http://www.gnu.org/licenses/gpl.html" target="_blank">GPLv3</a> License.</span> <span>My Thoughts Project under <a href="http://www.gnu.org/licenses/gpl.html" target="_blank">GPLv3</a> License.</span>
</footer> </footer>
#errors# #errors#

View File

@@ -1,111 +1,111 @@
<div id="write"> <div id="write">
<div id="write_feedback"></div> <div id="write_feedback"></div>
<div id="edi_write"></div> <div id="edi_write"></div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
oMyThoughts.pageInit = function(asHash, bFirstPage) oMyThoughts.pageInit = function(asHash, bFirstPage)
{ {
self.tmp('default_text', "\n"); self.tmp('default_text', "\n");
self.tmp('keystrokes', 0); self.tmp('keystrokes', 0);
self.tmp('saving', false); self.tmp('saving', false);
oEditor = new Editor('#edi_write'); oEditor = new Editor('#edi_write');
oEditor.onKeyStroke = (e) => { oEditor.onKeyStroke = (e) => {
if(e.which == 83 && e.ctrlKey) { if(e.which == 83 && e.ctrlKey) {
e.preventDefault(); e.preventDefault();
save(true); save(true);
} }
else save(); else save();
} }
oEditor.moveToPage('last'); oEditor.moveToPage('last');
}; };
oMyThoughts.onFeedback = function(sType, sMsg) oMyThoughts.onFeedback = function(sType, sMsg)
{ {
var $Feedback = $('#write_feedback').stop(); var $Feedback = $('#write_feedback').stop();
if(sMsg != $Feedback.find('span').text()) { if(sMsg != $Feedback.find('span').text()) {
$Feedback.fadeOut($Feedback.is(':empty')?0:'fast', function(){ $Feedback.fadeOut($Feedback.is(':empty')?0:'fast', function(){
$(this) $(this)
.empty() .empty()
.append($('<span>', {'class':sType}).text(sMsg)) .append($('<span>', {'class':sType}).text(sMsg))
.fadeIn('fast'); .fadeIn('fast');
}); });
} }
}; };
oMyThoughts.onQuitPage = function() oMyThoughts.onQuitPage = function()
{ {
return save(true); return save(true);
}; };
function save(bForce) function save(bForce)
{ {
if(typeof oSaveTimer != 'undefined') clearTimeout(oSaveTimer); if(typeof oSaveTimer != 'undefined') clearTimeout(oSaveTimer);
var bSave = (oEditor.keystrokes % 20 == 0 || bForce); var bSave = (oEditor.keystrokes % 20 == 0 || bForce);
if(bSave) { if(bSave) {
if(self.tmp('saving')) { if(self.tmp('saving')) {
oSaveTimer = setTimeout(function(){save(true);}, 500); oSaveTimer = setTimeout(function(){save(true);}, 500);
} }
else { else {
var sContent = oEditor.getContent(); var sContent = oEditor.getContent();
if(!oEditor.isEmpty() || oEditor.id != 0) { if(!oEditor.isEmpty() || oEditor.id != 0) {
self.tmp('saving', true); self.tmp('saving', true);
oMyThoughts.onFeedback('info', 'Saving...'); oMyThoughts.onFeedback('info', 'Saving...');
getInfo( getInfo(
'update', 'update',
function(sDesc, asData) { function(sDesc, asData) {
if(oEditor.id == 0) oMyThoughts.updateSideMenu(); if(oEditor.id == 0) oMyThoughts.updateSideMenu();
oEditor.id = asData.id; oEditor.id = asData.id;
oMyThoughts.feedback('notice', 'Thought saved ('+asData.led.substr(11, 5)+')'); oMyThoughts.feedback('notice', 'Thought saved ('+asData.led.substr(11, 5)+')');
self.tmp('saving', false); self.tmp('saving', false);
}, },
{ {
id: oEditor.id, id: oEditor.id,
content: sContent content: sContent
}, },
function(sError) { function(sError) {
oMyThoughts.feedback('error', 'Not saved! An error occured: '+sError); oMyThoughts.feedback('error', 'Not saved! An error occured: '+sError);
self.tmp('saving', false); self.tmp('saving', false);
oSaveTimer = setTimeout(save, 1000); oSaveTimer = setTimeout(save, 1000);
}, },
'POST' 'POST'
); );
} }
} }
} }
else { else {
oSaveTimer = setTimeout(function(){save(true);}, 1000*10); oSaveTimer = setTimeout(function(){save(true);}, 1000*10);
} }
return true; return true;
} }
/*function setLastContent(oQuill, fCallback) /*function setLastContent(oQuill, fCallback)
{ {
getInfo getInfo
( (
'load', 'load',
function(sDesc, asData) function(sDesc, asData)
{ {
if(asData.ops.length != 1 || asData.ops[0].insert != '' && false) { if(asData.ops.length != 1 || asData.ops[0].insert != '' && false) {
var $Date = $('<p>', {'class':'entry_date'}).text(asData.created_f); var $Date = $('<p>', {'class':'entry_date'}).text(asData.created_f);
var $Sep = $('<div>', {'class':'entry_sep'}) var $Sep = $('<div>', {'class':'entry_sep'})
.text('~') .text('~')
.click(function(){oQuill.focus();}); .click(function(){oQuill.focus();});
oQuill.setContents(asData.ops); oQuill.setContents(asData.ops);
$('#context') $('#context')
.append($('#editor .ql-editor').html()) .append($('#editor .ql-editor').html())
.append($Date) .append($Date)
.append($Sep); .append($Sep);
oQuill.setContents([]); oQuill.setContents([]);
} }
else oQuill.focus(); else oQuill.focus();
if(typeof fCallback == 'function') fCallback(); if(typeof fCallback == 'function') fCallback();
}, },
{id: 'last'} {id: 'last'}
); );
}*/ }*/
</script> </script>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,8 @@
/*! /*!
* jQuery Mousewheel 3.1.13 * jQuery Mousewheel 3.1.13
* *
* Copyright 2015 jQuery Foundation and other contributors * Copyright 2015 jQuery Foundation and other contributors
* Released under the MIT license. * Released under the MIT license.
* http://jquery.org/license * http://jquery.org/license
*/ */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})}); !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?module.exports=a:a(jQuery)}(function(a){function b(b){var g=b||window.event,h=i.call(arguments,1),j=0,l=0,m=0,n=0,o=0,p=0;if(b=a.event.fix(g),b.type="mousewheel","detail"in g&&(m=-1*g.detail),"wheelDelta"in g&&(m=g.wheelDelta),"wheelDeltaY"in g&&(m=g.wheelDeltaY),"wheelDeltaX"in g&&(l=-1*g.wheelDeltaX),"axis"in g&&g.axis===g.HORIZONTAL_AXIS&&(l=-1*m,m=0),j=0===m?l:m,"deltaY"in g&&(m=-1*g.deltaY,j=m),"deltaX"in g&&(l=g.deltaX,0===m&&(j=-1*l)),0!==m||0!==l){if(1===g.deltaMode){var q=a.data(this,"mousewheel-line-height");j*=q,m*=q,l*=q}else if(2===g.deltaMode){var r=a.data(this,"mousewheel-page-height");j*=r,m*=r,l*=r}if(n=Math.max(Math.abs(m),Math.abs(l)),(!f||f>n)&&(f=n,d(g,n)&&(f/=40)),d(g,n)&&(j/=40,l/=40,m/=40),j=Math[j>=1?"floor":"ceil"](j/f),l=Math[l>=1?"floor":"ceil"](l/f),m=Math[m>=1?"floor":"ceil"](m/f),k.settings.normalizeOffset&&this.getBoundingClientRect){var s=this.getBoundingClientRect();o=b.clientX-s.left,p=b.clientY-s.top}return b.deltaX=l,b.deltaY=m,b.deltaFactor=f,b.offsetX=o,b.offsetY=p,b.deltaMode=0,h.unshift(b,j,l,m),e&&clearTimeout(e),e=setTimeout(c,200),(a.event.dispatch||a.event.handle).apply(this,h)}}function c(){f=null}function d(a,b){return k.settings.adjustOldDeltas&&"mousewheel"===a.type&&b%120===0}var e,f,g=["wheel","mousewheel","DOMMouseScroll","MozMousePixelScroll"],h="onwheel"in document||document.documentMode>=9?["wheel"]:["mousewheel","DomMouseScroll","MozMousePixelScroll"],i=Array.prototype.slice;if(a.event.fixHooks)for(var j=g.length;j;)a.event.fixHooks[g[--j]]=a.event.mouseHooks;var k=a.event.special.mousewheel={version:"3.1.12",setup:function(){if(this.addEventListener)for(var c=h.length;c;)this.addEventListener(h[--c],b,!1);else this.onmousewheel=b;a.data(this,"mousewheel-line-height",k.getLineHeight(this)),a.data(this,"mousewheel-page-height",k.getPageHeight(this))},teardown:function(){if(this.removeEventListener)for(var c=h.length;c;)this.removeEventListener(h[--c],b,!1);else this.onmousewheel=null;a.removeData(this,"mousewheel-line-height"),a.removeData(this,"mousewheel-page-height")},getLineHeight:function(b){var c=a(b),d=c["offsetParent"in a.fn?"offsetParent":"parent"]();return d.length||(d=a("body")),parseInt(d.css("fontSize"),10)||parseInt(c.css("fontSize"),10)||16},getPageHeight:function(b){return a(b).height()},settings:{adjustOldDeltas:!0,normalizeOffset:!0}};a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})});

File diff suppressed because it is too large Load Diff

14
scripts/quill.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,21 +1,21 @@
$gray-100: lighten($col_main_1, 80%); //#ffffff $gray-100: lighten($col_main_1, 80%); //#ffffff
$gray-200: #e2ccb2; //Background $gray-200: #e2ccb2; //Background
$gray-300: lighten($col_main_1, 50%); //#d8c1a6 $gray-300: lighten($col_main_1, 50%); //#d8c1a6
$gray-400: lighten($col_main_1, 35%); //#c09b71 $gray-400: lighten($col_main_1, 35%); //#c09b71
$gray-500: lighten($col_main_1, 20%); //#9f7546 $gray-500: lighten($col_main_1, 20%); //#9f7546
$gray-600: lighten($col_main_1, 10%); //#7b5b37 $gray-600: lighten($col_main_1, 10%); //#7b5b37
$gray-700: $col_main_1; //#584127 $gray-700: $col_main_1; //#584127
$gray-800: darken($col_main_1, 10%); //#352717 $gray-800: darken($col_main_1, 10%); //#352717
$gray-900: darken($col_main_1, 20%); //#110d08 $gray-900: darken($col_main_1, 20%); //#110d08
$theme-colors: ( $theme-colors: (
"primary": $col_main_1, "primary": $col_main_1,
"secondary": $col_main_2, "secondary": $col_main_2,
"grey-400": $gray-400 "grey-400": $gray-400
); );
$theme-colors: map-remove($theme-colors, "light", "dark"); $theme-colors: map-remove($theme-colors, "light", "dark");
$font-family-base: $font_para; $font-family-base: $font_para;
@import 'bootstrap/bootstrap'; @import 'bootstrap/bootstrap';

View File

@@ -1,30 +1,30 @@
$fa-font-path: "fa/fonts"; $fa-font-path: "fa/fonts";
$fa-css-prefix: fa; $fa-css-prefix: fa;
@import 'fa/light'; @import 'fa/light';
@import 'fa/mixins'; @import 'fa/mixins';
@import 'fa/core'; @import 'fa/core';
@import 'fa/larger'; @import 'fa/larger';
@import 'fa/fixed-width'; @import 'fa/fixed-width';
@import 'fa/list'; @import 'fa/list';
@import 'fa/bordered-pulled'; @import 'fa/bordered-pulled';
@import 'fa/animated'; @import 'fa/animated';
@import 'fa/rotated-flipped'; @import 'fa/rotated-flipped';
@import 'fa/stacked'; @import 'fa/stacked';
.#{$fa-css-prefix}-user:before { content: fa-content($fa-var-user); } .#{$fa-css-prefix}-user:before { content: fa-content($fa-var-user); }
.#{$fa-css-prefix}-password:before { content: fa-content($fa-var-key); } .#{$fa-css-prefix}-password:before { content: fa-content($fa-var-key); }
//Menu //Menu
.#{$fa-css-prefix}-write:before { content: fa-content($fa-var-pen); } .#{$fa-css-prefix}-write:before { content: fa-content($fa-var-pen); }
.#{$fa-css-prefix}-settings:before { content: fa-content($fa-var-cog); } .#{$fa-css-prefix}-settings:before { content: fa-content($fa-var-cog); }
.#{$fa-css-prefix}-logoff:before { content: fa-content($fa-var-sign-out); } .#{$fa-css-prefix}-logoff:before { content: fa-content($fa-var-sign-out); }
//Writer //Writer
.#{$fa-css-prefix}-bold:before { content: fa-content($fa-var-bold); } .#{$fa-css-prefix}-bold:before { content: fa-content($fa-var-bold); }
.#{$fa-css-prefix}-underline:before { content: fa-content($fa-var-underline); } .#{$fa-css-prefix}-underline:before { content: fa-content($fa-var-underline); }
.#{$fa-css-prefix}-ol:before { content: fa-content($fa-var-list-ol); } .#{$fa-css-prefix}-ol:before { content: fa-content($fa-var-list-ol); }
.#{$fa-css-prefix}-ul:before { content: fa-content($fa-var-list-ul); } .#{$fa-css-prefix}-ul:before { content: fa-content($fa-var-list-ul); }
.#{$fa-css-prefix}-strike:before { content: fa-content($fa-var-strikethrough); } .#{$fa-css-prefix}-strike:before { content: fa-content($fa-var-strikethrough); }
.#{$fa-css-prefix}-prev:before { content: fa-content($fa-var-angle-left); } .#{$fa-css-prefix}-prev:before { content: fa-content($fa-var-angle-left); }
.#{$fa-css-prefix}-next:before { content: fa-content($fa-var-angle-right); } .#{$fa-css-prefix}-next:before { content: fa-content($fa-var-angle-right); }

View File

@@ -1,144 +1,146 @@
/* cyrillic-ext */ /* cyrillic-ext */
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(fonts/va9E4kDNxMZdWfMOD5VvmojLeTY.woff2) format('woff2'); src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(fonts/va9E4kDNxMZdWfMOD5VvmojLeTY.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
} }
/* cyrillic */ /* cyrillic */
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(https://fonts.gstatic.com/s/firasans/v8/va9E4kDNxMZdWfMOD5Vvk4jLeTY.woff2) format('woff2'); src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(https://fonts.gstatic.com/s/firasans/v8/va9E4kDNxMZdWfMOD5Vvk4jLeTY.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
/* greek-ext */ /* greek-ext */
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(https://fonts.gstatic.com/s/firasans/v8/va9E4kDNxMZdWfMOD5Vvm4jLeTY.woff2) format('woff2'); src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(https://fonts.gstatic.com/s/firasans/v8/va9E4kDNxMZdWfMOD5Vvm4jLeTY.woff2) format('woff2');
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
/* greek */ /* greek */
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(https://fonts.gstatic.com/s/firasans/v8/va9E4kDNxMZdWfMOD5VvlIjLeTY.woff2) format('woff2'); src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(https://fonts.gstatic.com/s/firasans/v8/va9E4kDNxMZdWfMOD5VvlIjLeTY.woff2) format('woff2');
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
/* vietnamese */ /* vietnamese */
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(https://fonts.gstatic.com/s/firasans/v8/va9E4kDNxMZdWfMOD5VvmIjLeTY.woff2) format('woff2'); src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(https://fonts.gstatic.com/s/firasans/v8/va9E4kDNxMZdWfMOD5VvmIjLeTY.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
} }
/* latin-ext */ /* latin-ext */
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(fonts/va9E4kDNxMZdWfMOD5VvmYjLeTY.woff2) format('woff2'); src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(fonts/va9E4kDNxMZdWfMOD5VvmYjLeTY.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Fira Sans'; font-family: 'Fira Sans';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(fonts/va9E4kDNxMZdWfMOD5Vvl4jL.woff2) format('woff2'); src: local('Fira Sans Regular'), local('FiraSans-Regular'), url(fonts/va9E4kDNxMZdWfMOD5Vvl4jL.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
} }
/* cyrillic-ext */ /* cyrillic-ext */
@font-face { @font-face {
font-family: 'Montserrat'; font-family: 'Montserrat';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v12/JTUSjIg1_i6t8kCHKm459WRhyzbi.woff2) format('woff2'); src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v12/JTUSjIg1_i6t8kCHKm459WRhyzbi.woff2) format('woff2');
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
} }
/* cyrillic */ /* cyrillic */
@font-face { @font-face {
font-family: 'Montserrat'; font-family: 'Montserrat';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v12/JTUSjIg1_i6t8kCHKm459W1hyzbi.woff2) format('woff2'); src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v12/JTUSjIg1_i6t8kCHKm459W1hyzbi.woff2) format('woff2');
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
/* vietnamese */ /* vietnamese */
@font-face { @font-face {
font-family: 'Montserrat'; font-family: 'Montserrat';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v12/JTUSjIg1_i6t8kCHKm459WZhyzbi.woff2) format('woff2'); src: local('Montserrat Regular'), local('Montserrat-Regular'), url(https://fonts.gstatic.com/s/montserrat/v12/JTUSjIg1_i6t8kCHKm459WZhyzbi.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
} }
/* latin-ext */ /* latin-ext */
@font-face { @font-face {
font-family: 'Montserrat'; font-family: 'Montserrat';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Montserrat Regular'), local('Montserrat-Regular'), url(fonts/JTUSjIg1_i6t8kCHKm459Wdhyzbi.woff2) format('woff2'); src: local('Montserrat Regular'), local('Montserrat-Regular'), url(fonts/JTUSjIg1_i6t8kCHKm459Wdhyzbi.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Montserrat'; font-family: 'Montserrat';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Montserrat Regular'), local('Montserrat-Regular'), url(fonts/JTUSjIg1_i6t8kCHKm459Wlhyw.woff2) format('woff2'); src: local('Montserrat Regular'), local('Montserrat-Regular'), url(fonts/JTUSjIg1_i6t8kCHKm459Wlhyw.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
} }
/* vietnamese */ /* vietnamese */
@font-face { @font-face {
font-family: 'Nunito'; font-family: 'Nunito';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Nunito Regular'), local('Nunito-Regular'), url(https://fonts.gstatic.com/s/nunito/v9/XRXV3I6Li01BKofIOuaBXso.woff2) format('woff2'); src: local('Nunito Regular'), local('Nunito-Regular'), url(https://fonts.gstatic.com/s/nunito/v9/XRXV3I6Li01BKofIOuaBXso.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
} }
/* latin-ext */ /* latin-ext */
@font-face { @font-face {
font-family: 'Nunito'; font-family: 'Nunito';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Nunito Regular'), local('Nunito-Regular'), url(fonts/XRXV3I6Li01BKofIO-aBXso.woff2) format('woff2'); src: local('Nunito Regular'), local('Nunito-Regular'), url(fonts/XRXV3I6Li01BKofIO-aBXso.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Nunito'; font-family: 'Nunito';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Nunito Regular'), local('Nunito-Regular'), url(fonts/XRXV3I6Li01BKofINeaB.woff2) format('woff2'); src: local('Nunito Regular'), local('Nunito-Regular'), url(fonts/XRXV3I6Li01BKofINeaB.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
} }
/* vietnamese */ /* vietnamese */
@font-face { @font-face {
font-family: 'Quicksand'; font-family: 'Quicksand';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Quicksand Regular'), local('Quicksand-Regular'), url(https://fonts.gstatic.com/s/quicksand/v8/6xKtdSZaM9iE8KbpRA_hJFQNcOM.woff2) format('woff2'); src: local('Quicksand Regular'), local('Quicksand-Regular'), url(https://fonts.gstatic.com/s/quicksand/v8/6xKtdSZaM9iE8KbpRA_hJFQNcOM.woff2) format('woff2');
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
} }
/* latin-ext */ /* latin-ext */
@font-face { @font-face {
font-family: 'Quicksand'; font-family: 'Quicksand';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Quicksand Regular'), local('Quicksand-Regular'), url(fonts/6xKtdSZaM9iE8KbpRA_hJVQNcOM.woff2) format('woff2'); src: local('Quicksand Regular'), local('Quicksand-Regular'), url(fonts/6xKtdSZaM9iE8KbpRA_hJVQNcOM.woff2) format('woff2');
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
} }
/* latin */ /* latin */
@font-face { @font-face {
font-family: 'Quicksand'; font-family: 'Quicksand';
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Quicksand Regular'), local('Quicksand-Regular'), url(fonts/6xKtdSZaM9iE8KbpRA_hK1QN.woff2) format('woff2'); src: local('Quicksand Regular'), local('Quicksand-Regular'), url(fonts/6xKtdSZaM9iE8KbpRA_hK1QN.woff2) format('woff2');
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
} }
@import url('https://fonts.googleapis.com/css?family=Open+Sans:700|Titillium+Web');

View File

@@ -1,27 +1,27 @@
/* Log on */ /* Log on */
#logon { #logon {
width: 300px; width: 300px;
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
position: absolute; position: absolute;
left: 50%; left: 50%;
top: 40%; top: 40%;
padding: 1em; padding: 1em;
#pass_conf_box { #pass_conf_box {
.fa-password { .fa-password {
&.first { &.first {
margin: -0.25em 0.25em 0 -0.25em; margin: -0.25em 0.25em 0 -0.25em;
} }
&.second { &.second {
position: absolute; position: absolute;
margin: 0.25em 0 0 0.25em; margin: 0.25em 0 0 0.25em;
} }
} }
} }
#btn_box.registering #register { #btn_box.registering #register {
margin-left: 100%; margin-left: 100%;
transform: translateX(-100%); transform: translateX(-100%);
} }
} }

View File

@@ -1,80 +1,80 @@
@import 'quill/quill.bubble'; @import 'quill/quill.bubble';
.ql-editor.ql-blank::before { .ql-editor.ql-blank::before {
left: 1.5em; left: 1.5em;
color: $gray-400; color: $gray-400;
} }
.editor { .editor {
position: relative; position: relative;
height:100%; height:100%;
.edi_container { .edi_container {
height: calc(100% - 2em); /* 2 * 2em*/ height: calc(100% - 2em); /* 2 * 2em*/
overflow: hidden; overflow: hidden;
position: relative; position: relative;
.edi_content { .edi_content {
height:auto; height:auto;
position: relative; position: relative;
.ql-container { .ql-container {
padding: 0; padding: 0;
} }
.ql-editor { .ql-editor {
padding: 0; padding: 0;
font-family: $font_para; font-family: $font_para;
font-size: 14px; font-size: 14px;
div { div {
margin: 0; margin: 0;
&.edi_header { &.edi_header {
color: $gray-500; color: $gray-500;
font-style: italic; font-style: italic;
line-height: 3em; line-height: 3em;
} }
} }
p { p {
text-indent: 1.5em; text-indent: 1.5em;
margin: 0; margin: 0;
padding: 0; padding: 0;
text-align: justify; text-align: justify;
line-height: 1.5em; line-height: 1.5em;
} }
} }
} }
} }
/* Write - Navbar */ /* Write - Navbar */
.edi_nav { .edi_nav {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
right: 0; right: 0;
left: 0; left: 0;
.nav-elem { .nav-elem {
color: $gray-500; color: $gray-500;
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
width: 1.25em; width: 1.25em;
font-size: 1.25em; font-size: 1.25em;
&:hover { &:hover {
color: $gray-700; color: $gray-700;
} }
&.prev, &.curr, &.next { &.prev, &.curr, &.next {
visibility: hidden; visibility: hidden;
} }
&.next { &.next {
float: right; float: right;
} }
} }
} }
} }

View File

@@ -1,9 +1,9 @@
#read { #read {
.header { .header {
} }
.body { .body {
} }
} }

View File

@@ -1,243 +1,243 @@
/* Containers */ /* Containers */
body { body {
min-width: 700px; min-width: 700px;
font-family: $font_para, sans-serif; font-family: $font_para, sans-serif;
font-size:1em; font-size:1em;
background-color: $gray-200; background-color: $gray-200;
margin:0; margin:0;
color: $col_main_1; color: $col_main_1;
} }
/* Typography */ /* Typography */
a:visited, a { a:visited, a {
color: $col_main_1; color: $col_main_1;
text-decoration: none; text-decoration: none;
font-weight: bold; font-weight: bold;
} }
a:active, a:focus, input:active, input:focus { a:active, a:focus, input:active, input:focus {
outline: none; outline: none;
} }
a:hover { a:hover {
text-decoration: none; text-decoration: none;
} }
/* Common Classes */ /* Common Classes */
.transition { .transition {
transition: all 0.3s ease 0s !important; transition: all 0.3s ease 0s !important;
} }
.bold { .bold {
font-weight: bold; font-weight: bold;
} }
/* Common Classes - Containers */ /* Common Classes - Containers */
#container { #container {
position:absolute; position:absolute;
left:0; left:0;
right:0; right:0;
top:1em; top:1em;
bottom:1em; bottom:1em;
width:40em; width:40em;
margin:auto; margin:auto;
} }
/* Common Classes - Inputs */ /* Common Classes - Inputs */
a.button { a.button {
font-weight:normal; font-weight:normal;
height:50px; height:50px;
width:50px; width:50px;
line-height:50px; line-height:50px;
font-size: 1.0em; font-size: 1.0em;
text-align:center; text-align:center;
background: url("../images/minicloud.png") 0 0 no-repeat; background: url("../images/minicloud.png") 0 0 no-repeat;
color: $gray-600; color: $gray-600;
} }
a.button:hover { a.button:hover {
color:white; color:white;
background-position:0 -50px; background-position:0 -50px;
} }
a.button:active { a.button:active {
color:white; color:white;
background-position:0 -100px; background-position:0 -100px;
} }
.input-group-text i.fal { .input-group-text i.fal {
@extend .fa-fw; @extend .fa-fw;
} }
/* Common Classes - Feedback */ /* Common Classes - Feedback */
#feedback { #feedback {
position: absolute; position: absolute;
width: 100%; width: 100%;
z-index: 1000; z-index: 1000;
.alert { .alert {
top: 1em; top: 1em;
background: $gray-200; background: $gray-200;
} }
} }
/* Header */ /* Header */
#header { #header {
margin-left:-100px; margin-left:-100px;
height:203px; height:203px;
background:url('../images/logo.png') 0 0 no-repeat; background:url('../images/logo.png') 0 0 no-repeat;
} }
/* Menu */ /* Menu */
#menu { #menu {
position: absolute; position: absolute;
display: none; display: none;
top: 0; top: 0;
right: 0; right: 0;
ul { ul {
list-style: none; list-style: none;
li { li {
display: inline; display: inline;
} }
} }
} }
/* Main */ /* Main */
#main { #main {
display: none; display: none;
margin-top: 1em; margin-top: 1em;
position: absolute; position: absolute;
top:203px; top:203px;
bottom: 2rem; bottom: 2rem;
right:0; right:0;
left:0; left:0;
border-radius: 0.5em; border-radius: 0.5em;
padding: 1em; padding: 1em;
&:not(.no_frame) { &:not(.no_frame) {
@extend .shadow; @extend .shadow;
} }
} }
/* Side */ /* Side */
#side { #side {
position: absolute; position: absolute;
left: 100%; left: 100%;
top: 203px; top: 203px;
padding: 1em; padding: 1em;
bottom: 2rem; bottom: 2rem;
overflow: hidden; overflow: hidden;
display: none; display: none;
.tag { .tag {
margin-bottom: 1em; margin-bottom: 1em;
a { a {
@extend .shadow; @extend .shadow;
display: inline-block; display: inline-block;
text-align: center; text-align: center;
width: 50px; width: 50px;
background: $gray-200; background: $gray-200;
border-radius: 0.5em; border-radius: 0.5em;
font-size: 0.8rem; font-size: 0.8rem;
line-height: 25px; line-height: 25px;
&:hover { &:hover {
color: $gray-200; color: $gray-200;
background: $gray-400; background: $gray-400;
} }
} }
&.write a { &.write a {
font-size: 1rem; font-size: 1rem;
padding: 0; padding: 0;
line-height: 50px; line-height: 50px;
} }
} }
} }
/* Settings */ /* Settings */
#settings table tr td { #settings table tr td {
text-align:left; text-align:left;
} }
/* Errors */ /* Errors */
#errors { #errors {
position:fixed; position:fixed;
bottom:-2px; bottom:-2px;
background-color:white; background-color:white;
width:696px; width:696px;
border:2px solid red; border:2px solid red;
} }
#errors ul li { #errors ul li {
list-style-image: url(../images/error.png); list-style-image: url(../images/error.png);
color:red; color:red;
font-weight: bold; font-weight: bold;
font-size:24px; font-size:24px;
} }
fieldset { fieldset {
margin:20px auto; margin:20px auto;
width:90%; width:90%;
} }
fieldset p { fieldset p {
text-align: justify; text-align: justify;
} }
/* Feedback */ /* Feedback */
.notice { .notice {
padding:0; padding:0;
color:#997E60; color:#997E60;
} }
.error { .error {
padding:0 0.5em; padding:0 0.5em;
color: red; color: red;
background:#FFB2B2; background:#FFB2B2;
} }
.warning { .warning {
padding:0 0.5em; padding:0 0.5em;
color:orange; color:orange;
background:#FFE4B2; background:#FFE4B2;
} }
.success { .success {
padding:0 0.5em; padding:0 0.5em;
color:green; color:green;
background:#B2D9B2; background:#B2D9B2;
} }
/* Footer */ /* Footer */
footer { footer {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
text-align: center; text-align: center;
color: $gray-400; color: $gray-400;
font-size: 0.8em; font-size: 0.8em;
width: 100%; width: 100%;
height: 2rem; height: 2rem;
span { span {
transform: translateY(-50%); transform: translateY(-50%);
position: relative; position: relative;
top: 50%; top: 50%;
a { a {
color: $gray-400 !important; color: $gray-400 !important;
} }
} }
} }

View File

@@ -1,13 +1,13 @@
/* Colors /* Colors
Very Very Bright Brown: #f7f2eb Very Very Bright Brown: #f7f2eb
Very Bright Brown: #ede0d0 Very Bright Brown: #ede0d0
bright brown : #e2ccb2 bright brown : #e2ccb2
dark brown : #584127 dark brown : #584127
blue lines : #2DCDFF blue lines : #2DCDFF
red lines : #EC3B45 red lines : #EC3B45
*/ */
$col_main_1: #584127; //Primary $col_main_1: #584127; //Primary
$col_main_2: #355078; //Complementary to Primary $col_main_2: #355078; //Complementary to Primary
$font_para: 'Quicksand'; $font_para: 'Quicksand';

View File

@@ -1,31 +1,31 @@
#write { #write {
position: relative; position: relative;
height:100%; height:100%;
#context { #context {
.entry_date { .entry_date {
text-align: right; text-align: right;
} }
.entry_sep { .entry_sep {
font-size: 1.5em; font-size: 1.5em;
text-align: center; text-align: center;
letter-spacing: 0.3em; letter-spacing: 0.3em;
padding: 1em; padding: 1em;
} }
} }
/* Write - Feedback */ /* Write - Feedback */
#write_feedback { #write_feedback {
position:absolute; position:absolute;
top: -2.5rem; top: -2.5rem;
right: -1rem; right: -1rem;
font-size: 0.8em; font-size: 0.8em;
.notice { .notice {
color: $gray-400; color: $gray-400;
} }
} }
} }

View File

@@ -1,47 +1,47 @@
// Base class // Base class
// //
// Requires one of the contextual, color modifier classes for `color` and // Requires one of the contextual, color modifier classes for `color` and
// `background-color`. // `background-color`.
.badge { .badge {
display: inline-block; display: inline-block;
padding: $badge-padding-y $badge-padding-x; padding: $badge-padding-y $badge-padding-x;
font-size: $badge-font-size; font-size: $badge-font-size;
font-weight: $badge-font-weight; font-weight: $badge-font-weight;
line-height: 1; line-height: 1;
text-align: center; text-align: center;
white-space: nowrap; white-space: nowrap;
vertical-align: baseline; vertical-align: baseline;
@include border-radius($badge-border-radius); @include border-radius($badge-border-radius);
// Empty badges collapse automatically // Empty badges collapse automatically
&:empty { &:empty {
display: none; display: none;
} }
} }
// Quick fix for badges in buttons // Quick fix for badges in buttons
.btn .badge { .btn .badge {
position: relative; position: relative;
top: -1px; top: -1px;
} }
// Pill badges // Pill badges
// //
// Make them extra rounded with a modifier to replace v3's badges. // Make them extra rounded with a modifier to replace v3's badges.
.badge-pill { .badge-pill {
padding-right: $badge-pill-padding-x; padding-right: $badge-pill-padding-x;
padding-left: $badge-pill-padding-x; padding-left: $badge-pill-padding-x;
@include border-radius($badge-pill-border-radius); @include border-radius($badge-pill-border-radius);
} }
// Colors // Colors
// //
// Contextual variations (linked badges get darker on :hover). // Contextual variations (linked badges get darker on :hover).
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
.badge-#{$color} { .badge-#{$color} {
@include badge-variant($value); @include badge-variant($value);
} }
} }

View File

@@ -1,41 +1,41 @@
.breadcrumb { .breadcrumb {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding: $breadcrumb-padding-y $breadcrumb-padding-x; padding: $breadcrumb-padding-y $breadcrumb-padding-x;
margin-bottom: $breadcrumb-margin-bottom; margin-bottom: $breadcrumb-margin-bottom;
list-style: none; list-style: none;
background-color: $breadcrumb-bg; background-color: $breadcrumb-bg;
@include border-radius($breadcrumb-border-radius); @include border-radius($breadcrumb-border-radius);
} }
.breadcrumb-item { .breadcrumb-item {
// The separator between breadcrumbs (by default, a forward-slash: "/") // The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item { + .breadcrumb-item {
padding-left: $breadcrumb-item-padding; padding-left: $breadcrumb-item-padding;
&::before { &::before {
display: inline-block; // Suppress underlining of the separator in modern browsers display: inline-block; // Suppress underlining of the separator in modern browsers
padding-right: $breadcrumb-item-padding; padding-right: $breadcrumb-item-padding;
color: $breadcrumb-divider-color; color: $breadcrumb-divider-color;
content: $breadcrumb-divider; content: $breadcrumb-divider;
} }
} }
// IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built // IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built
// without `<ul>`s. The `::before` pseudo-element generates an element // without `<ul>`s. The `::before` pseudo-element generates an element
// *within* the .breadcrumb-item and thereby inherits the `text-decoration`. // *within* the .breadcrumb-item and thereby inherits the `text-decoration`.
// //
// To trick IE into suppressing the underline, we give the pseudo-element an // To trick IE into suppressing the underline, we give the pseudo-element an
// underline and then immediately remove it. // underline and then immediately remove it.
+ .breadcrumb-item:hover::before { + .breadcrumb-item:hover::before {
text-decoration: underline; text-decoration: underline;
} }
// stylelint-disable-next-line no-duplicate-selectors // stylelint-disable-next-line no-duplicate-selectors
+ .breadcrumb-item:hover::before { + .breadcrumb-item:hover::before {
text-decoration: none; text-decoration: none;
} }
&.active { &.active {
color: $breadcrumb-active-color; color: $breadcrumb-active-color;
} }
} }

View File

@@ -1,172 +1,172 @@
// stylelint-disable selector-no-qualifying-type // stylelint-disable selector-no-qualifying-type
// Make the div behave like a button // Make the div behave like a button
.btn-group, .btn-group,
.btn-group-vertical { .btn-group-vertical {
position: relative; position: relative;
display: inline-flex; display: inline-flex;
vertical-align: middle; // match .btn alignment given font-size hack above vertical-align: middle; // match .btn alignment given font-size hack above
> .btn { > .btn {
position: relative; position: relative;
flex: 0 1 auto; flex: 0 1 auto;
// Bring the hover, focused, and "active" buttons to the front to overlay // Bring the hover, focused, and "active" buttons to the front to overlay
// the borders properly // the borders properly
@include hover { @include hover {
z-index: 1; z-index: 1;
} }
&:focus, &:focus,
&:active, &:active,
&.active { &.active {
z-index: 1; z-index: 1;
} }
} }
// Prevent double borders when buttons are next to each other // Prevent double borders when buttons are next to each other
.btn + .btn, .btn + .btn,
.btn + .btn-group, .btn + .btn-group,
.btn-group + .btn, .btn-group + .btn,
.btn-group + .btn-group { .btn-group + .btn-group {
margin-left: -$btn-border-width; margin-left: -$btn-border-width;
} }
} }
// Optional: Group multiple button groups together for a toolbar // Optional: Group multiple button groups together for a toolbar
.btn-toolbar { .btn-toolbar {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: flex-start; justify-content: flex-start;
.input-group { .input-group {
width: auto; width: auto;
} }
} }
.btn-group { .btn-group {
> .btn:first-child { > .btn:first-child {
margin-left: 0; margin-left: 0;
} }
// Reset rounded corners // Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle), > .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn { > .btn-group:not(:last-child) > .btn {
@include border-right-radius(0); @include border-right-radius(0);
} }
> .btn:not(:first-child), > .btn:not(:first-child),
> .btn-group:not(:first-child) > .btn { > .btn-group:not(:first-child) > .btn {
@include border-left-radius(0); @include border-left-radius(0);
} }
} }
// Sizing // Sizing
// //
// Remix the default button sizing classes into new ones for easier manipulation. // Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-sm > .btn { @extend .btn-sm; } .btn-group-sm > .btn { @extend .btn-sm; }
.btn-group-lg > .btn { @extend .btn-lg; } .btn-group-lg > .btn { @extend .btn-lg; }
// //
// Split button dropdowns // Split button dropdowns
// //
.dropdown-toggle-split { .dropdown-toggle-split {
padding-right: $btn-padding-x * .75; padding-right: $btn-padding-x * .75;
padding-left: $btn-padding-x * .75; padding-left: $btn-padding-x * .75;
&::after, &::after,
.dropup &::after, .dropup &::after,
.dropright &::after { .dropright &::after {
margin-left: 0; margin-left: 0;
} }
.dropleft &::before { .dropleft &::before {
margin-right: 0; margin-right: 0;
} }
} }
.btn-sm + .dropdown-toggle-split { .btn-sm + .dropdown-toggle-split {
padding-right: $btn-padding-x-sm * .75; padding-right: $btn-padding-x-sm * .75;
padding-left: $btn-padding-x-sm * .75; padding-left: $btn-padding-x-sm * .75;
} }
.btn-lg + .dropdown-toggle-split { .btn-lg + .dropdown-toggle-split {
padding-right: $btn-padding-x-lg * .75; padding-right: $btn-padding-x-lg * .75;
padding-left: $btn-padding-x-lg * .75; padding-left: $btn-padding-x-lg * .75;
} }
// The clickable button for toggling the menu // The clickable button for toggling the menu
// Set the same inset shadow as the :active state // Set the same inset shadow as the :active state
.btn-group.show .dropdown-toggle { .btn-group.show .dropdown-toggle {
@include box-shadow($btn-active-box-shadow); @include box-shadow($btn-active-box-shadow);
// Show no shadow for `.btn-link` since it has no other button styles. // Show no shadow for `.btn-link` since it has no other button styles.
&.btn-link { &.btn-link {
@include box-shadow(none); @include box-shadow(none);
} }
} }
// //
// Vertical button groups // Vertical button groups
// //
.btn-group-vertical { .btn-group-vertical {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
justify-content: center; justify-content: center;
.btn, .btn,
.btn-group { .btn-group {
width: 100%; width: 100%;
} }
> .btn + .btn, > .btn + .btn,
> .btn + .btn-group, > .btn + .btn-group,
> .btn-group + .btn, > .btn-group + .btn,
> .btn-group + .btn-group { > .btn-group + .btn-group {
margin-top: -$btn-border-width; margin-top: -$btn-border-width;
margin-left: 0; margin-left: 0;
} }
// Reset rounded corners // Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle), > .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn { > .btn-group:not(:last-child) > .btn {
@include border-bottom-radius(0); @include border-bottom-radius(0);
} }
> .btn:not(:first-child), > .btn:not(:first-child),
> .btn-group:not(:first-child) > .btn { > .btn-group:not(:first-child) > .btn {
@include border-top-radius(0); @include border-top-radius(0);
} }
} }
// Checkbox and radio options // Checkbox and radio options
// //
// In order to support the browser's form validation feedback, powered by the // In order to support the browser's form validation feedback, powered by the
// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use // `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
// `display: none;` or `visibility: hidden;` as that also hides the popover. // `display: none;` or `visibility: hidden;` as that also hides the popover.
// Simply visually hiding the inputs via `opacity` would leave them clickable in // Simply visually hiding the inputs via `opacity` would leave them clickable in
// certain cases which is prevented by using `clip` and `pointer-events`. // certain cases which is prevented by using `clip` and `pointer-events`.
// This way, we ensure a DOM element is visible to position the popover from. // This way, we ensure a DOM element is visible to position the popover from.
// //
// See https://github.com/twbs/bootstrap/pull/12794 and // See https://github.com/twbs/bootstrap/pull/12794 and
// https://github.com/twbs/bootstrap/pull/14559 for more information. // https://github.com/twbs/bootstrap/pull/14559 for more information.
.btn-group-toggle { .btn-group-toggle {
> .btn, > .btn,
> .btn-group > .btn { > .btn-group > .btn {
margin-bottom: 0; // Override default `<label>` value margin-bottom: 0; // Override default `<label>` value
input[type="radio"], input[type="radio"],
input[type="checkbox"] { input[type="checkbox"] {
position: absolute; position: absolute;
clip: rect(0, 0, 0, 0); clip: rect(0, 0, 0, 0);
pointer-events: none; pointer-events: none;
} }
} }
} }

View File

@@ -1,144 +1,144 @@
// stylelint-disable selector-no-qualifying-type // stylelint-disable selector-no-qualifying-type
// //
// Base styles // Base styles
// //
.btn { .btn {
display: inline-block; display: inline-block;
font-weight: $btn-font-weight; font-weight: $btn-font-weight;
text-align: center; text-align: center;
white-space: nowrap; white-space: nowrap;
vertical-align: middle; vertical-align: middle;
user-select: none; user-select: none;
border: $btn-border-width solid transparent; border: $btn-border-width solid transparent;
@include button-size($btn-padding-y, $btn-padding-x, $font-size-base, $btn-line-height, $btn-border-radius); @include button-size($btn-padding-y, $btn-padding-x, $font-size-base, $btn-line-height, $btn-border-radius);
@include transition($btn-transition); @include transition($btn-transition);
// Share hover and focus styles // Share hover and focus styles
@include hover-focus { @include hover-focus {
text-decoration: none; text-decoration: none;
} }
&:focus, &:focus,
&.focus { &.focus {
outline: 0; outline: 0;
box-shadow: $btn-focus-box-shadow; box-shadow: $btn-focus-box-shadow;
} }
// Disabled comes first so active can properly restyle // Disabled comes first so active can properly restyle
&.disabled, &.disabled,
&:disabled { &:disabled {
opacity: $btn-disabled-opacity; opacity: $btn-disabled-opacity;
@include box-shadow(none); @include box-shadow(none);
} }
// Opinionated: add "hand" cursor to non-disabled .btn elements // Opinionated: add "hand" cursor to non-disabled .btn elements
&:not(:disabled):not(.disabled) { &:not(:disabled):not(.disabled) {
cursor: pointer; cursor: pointer;
} }
&:not(:disabled):not(.disabled):active, &:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled).active { &:not(:disabled):not(.disabled).active {
background-image: none; background-image: none;
@include box-shadow($btn-active-box-shadow); @include box-shadow($btn-active-box-shadow);
&:focus { &:focus {
@include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow); @include box-shadow($btn-focus-box-shadow, $btn-active-box-shadow);
} }
} }
} }
// Future-proof disabling of clicks on `<a>` elements // Future-proof disabling of clicks on `<a>` elements
a.btn.disabled, a.btn.disabled,
fieldset:disabled a.btn { fieldset:disabled a.btn {
pointer-events: none; pointer-events: none;
} }
// //
// Alternate buttons // Alternate buttons
// //
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
.btn-#{$color} { .btn-#{$color} {
@include button-variant($value, $value); @include button-variant($value, $value);
} }
} }
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
.btn-outline-#{$color} { .btn-outline-#{$color} {
@include button-outline-variant($value); @include button-outline-variant($value);
} }
} }
// //
// Link buttons // Link buttons
// //
// Make a button look and behave like a link // Make a button look and behave like a link
.btn-link { .btn-link {
font-weight: $font-weight-normal; font-weight: $font-weight-normal;
color: $link-color; color: $link-color;
background-color: transparent; background-color: transparent;
@include hover { @include hover {
color: $link-hover-color; color: $link-hover-color;
text-decoration: $link-hover-decoration; text-decoration: $link-hover-decoration;
background-color: transparent; background-color: transparent;
border-color: transparent; border-color: transparent;
} }
&:focus, &:focus,
&.focus { &.focus {
text-decoration: $link-hover-decoration; text-decoration: $link-hover-decoration;
border-color: transparent; border-color: transparent;
box-shadow: none; box-shadow: none;
} }
&:disabled, &:disabled,
&.disabled { &.disabled {
color: $btn-link-disabled-color; color: $btn-link-disabled-color;
pointer-events: none; pointer-events: none;
} }
// No need for an active state here // No need for an active state here
} }
// //
// Button Sizes // Button Sizes
// //
.btn-lg { .btn-lg {
@include button-size($btn-padding-y-lg, $btn-padding-x-lg, $font-size-lg, $btn-line-height-lg, $btn-border-radius-lg); @include button-size($btn-padding-y-lg, $btn-padding-x-lg, $font-size-lg, $btn-line-height-lg, $btn-border-radius-lg);
} }
.btn-sm { .btn-sm {
@include button-size($btn-padding-y-sm, $btn-padding-x-sm, $font-size-sm, $btn-line-height-sm, $btn-border-radius-sm); @include button-size($btn-padding-y-sm, $btn-padding-x-sm, $font-size-sm, $btn-line-height-sm, $btn-border-radius-sm);
} }
// //
// Block button // Block button
// //
.btn-block { .btn-block {
display: block; display: block;
width: 100%; width: 100%;
// Vertically space out multiple block buttons // Vertically space out multiple block buttons
+ .btn-block { + .btn-block {
margin-top: $btn-block-spacing-y; margin-top: $btn-block-spacing-y;
} }
} }
// Specificity overrides // Specificity overrides
input[type="submit"], input[type="submit"],
input[type="reset"], input[type="reset"],
input[type="button"] { input[type="button"] {
&.btn-block { &.btn-block {
width: 100%; width: 100%;
} }
} }

View File

@@ -1,301 +1,301 @@
// //
// Base styles // Base styles
// //
.card { .card {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-width: 0; min-width: 0;
word-wrap: break-word; word-wrap: break-word;
background-color: $card-bg; background-color: $card-bg;
background-clip: border-box; background-clip: border-box;
border: $card-border-width solid $card-border-color; border: $card-border-width solid $card-border-color;
@include border-radius($card-border-radius); @include border-radius($card-border-radius);
> hr { > hr {
margin-right: 0; margin-right: 0;
margin-left: 0; margin-left: 0;
} }
> .list-group:first-child { > .list-group:first-child {
.list-group-item:first-child { .list-group-item:first-child {
@include border-top-radius($card-border-radius); @include border-top-radius($card-border-radius);
} }
} }
> .list-group:last-child { > .list-group:last-child {
.list-group-item:last-child { .list-group-item:last-child {
@include border-bottom-radius($card-border-radius); @include border-bottom-radius($card-border-radius);
} }
} }
} }
.card-body { .card-body {
// Enable `flex-grow: 1` for decks and groups so that card blocks take up // Enable `flex-grow: 1` for decks and groups so that card blocks take up
// as much space as possible, ensuring footers are aligned to the bottom. // as much space as possible, ensuring footers are aligned to the bottom.
flex: 1 1 auto; flex: 1 1 auto;
padding: $card-spacer-x; padding: $card-spacer-x;
} }
.card-title { .card-title {
margin-bottom: $card-spacer-y; margin-bottom: $card-spacer-y;
} }
.card-subtitle { .card-subtitle {
margin-top: -($card-spacer-y / 2); margin-top: -($card-spacer-y / 2);
margin-bottom: 0; margin-bottom: 0;
} }
.card-text:last-child { .card-text:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
.card-link { .card-link {
@include hover { @include hover {
text-decoration: none; text-decoration: none;
} }
+ .card-link { + .card-link {
margin-left: $card-spacer-x; margin-left: $card-spacer-x;
} }
} }
// //
// Optional textual caps // Optional textual caps
// //
.card-header { .card-header {
padding: $card-spacer-y $card-spacer-x; padding: $card-spacer-y $card-spacer-x;
margin-bottom: 0; // Removes the default margin-bottom of <hN> margin-bottom: 0; // Removes the default margin-bottom of <hN>
background-color: $card-cap-bg; background-color: $card-cap-bg;
border-bottom: $card-border-width solid $card-border-color; border-bottom: $card-border-width solid $card-border-color;
&:first-child { &:first-child {
@include border-radius($card-inner-border-radius $card-inner-border-radius 0 0); @include border-radius($card-inner-border-radius $card-inner-border-radius 0 0);
} }
+ .list-group { + .list-group {
.list-group-item:first-child { .list-group-item:first-child {
border-top: 0; border-top: 0;
} }
} }
} }
.card-footer { .card-footer {
padding: $card-spacer-y $card-spacer-x; padding: $card-spacer-y $card-spacer-x;
background-color: $card-cap-bg; background-color: $card-cap-bg;
border-top: $card-border-width solid $card-border-color; border-top: $card-border-width solid $card-border-color;
&:last-child { &:last-child {
@include border-radius(0 0 $card-inner-border-radius $card-inner-border-radius); @include border-radius(0 0 $card-inner-border-radius $card-inner-border-radius);
} }
} }
// //
// Header navs // Header navs
// //
.card-header-tabs { .card-header-tabs {
margin-right: -($card-spacer-x / 2); margin-right: -($card-spacer-x / 2);
margin-bottom: -$card-spacer-y; margin-bottom: -$card-spacer-y;
margin-left: -($card-spacer-x / 2); margin-left: -($card-spacer-x / 2);
border-bottom: 0; border-bottom: 0;
} }
.card-header-pills { .card-header-pills {
margin-right: -($card-spacer-x / 2); margin-right: -($card-spacer-x / 2);
margin-left: -($card-spacer-x / 2); margin-left: -($card-spacer-x / 2);
} }
// Card image // Card image
.card-img-overlay { .card-img-overlay {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
padding: $card-img-overlay-padding; padding: $card-img-overlay-padding;
} }
.card-img { .card-img {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
@include border-radius($card-inner-border-radius); @include border-radius($card-inner-border-radius);
} }
// Card image caps // Card image caps
.card-img-top { .card-img-top {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
@include border-top-radius($card-inner-border-radius); @include border-top-radius($card-inner-border-radius);
} }
.card-img-bottom { .card-img-bottom {
width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch width: 100%; // Required because we use flexbox and this inherently applies align-self: stretch
@include border-bottom-radius($card-inner-border-radius); @include border-bottom-radius($card-inner-border-radius);
} }
// Card deck // Card deck
.card-deck { .card-deck {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
.card { .card {
margin-bottom: $card-deck-margin; margin-bottom: $card-deck-margin;
} }
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
flex-flow: row wrap; flex-flow: row wrap;
margin-right: -$card-deck-margin; margin-right: -$card-deck-margin;
margin-left: -$card-deck-margin; margin-left: -$card-deck-margin;
.card { .card {
display: flex; display: flex;
// Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4 // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
flex: 1 0 0%; flex: 1 0 0%;
flex-direction: column; flex-direction: column;
margin-right: $card-deck-margin; margin-right: $card-deck-margin;
margin-bottom: 0; // Override the default margin-bottom: 0; // Override the default
margin-left: $card-deck-margin; margin-left: $card-deck-margin;
} }
} }
} }
// //
// Card groups // Card groups
// //
.card-group { .card-group {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
// The child selector allows nested `.card` within `.card-group` // The child selector allows nested `.card` within `.card-group`
// to display properly. // to display properly.
> .card { > .card {
margin-bottom: $card-group-margin; margin-bottom: $card-group-margin;
} }
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
flex-flow: row wrap; flex-flow: row wrap;
// The child selector allows nested `.card` within `.card-group` // The child selector allows nested `.card` within `.card-group`
// to display properly. // to display properly.
> .card { > .card {
// Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4 // Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
flex: 1 0 0%; flex: 1 0 0%;
margin-bottom: 0; margin-bottom: 0;
+ .card { + .card {
margin-left: 0; margin-left: 0;
border-left: 0; border-left: 0;
} }
// Handle rounded corners // Handle rounded corners
@if $enable-rounded { @if $enable-rounded {
&:first-child { &:first-child {
@include border-right-radius(0); @include border-right-radius(0);
.card-img-top, .card-img-top,
.card-header { .card-header {
border-top-right-radius: 0; border-top-right-radius: 0;
} }
.card-img-bottom, .card-img-bottom,
.card-footer { .card-footer {
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
} }
} }
&:last-child { &:last-child {
@include border-left-radius(0); @include border-left-radius(0);
.card-img-top, .card-img-top,
.card-header { .card-header {
border-top-left-radius: 0; border-top-left-radius: 0;
} }
.card-img-bottom, .card-img-bottom,
.card-footer { .card-footer {
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
} }
} }
&:only-child { &:only-child {
@include border-radius($card-border-radius); @include border-radius($card-border-radius);
.card-img-top, .card-img-top,
.card-header { .card-header {
@include border-top-radius($card-border-radius); @include border-top-radius($card-border-radius);
} }
.card-img-bottom, .card-img-bottom,
.card-footer { .card-footer {
@include border-bottom-radius($card-border-radius); @include border-bottom-radius($card-border-radius);
} }
} }
&:not(:first-child):not(:last-child):not(:only-child) { &:not(:first-child):not(:last-child):not(:only-child) {
@include border-radius(0); @include border-radius(0);
.card-img-top, .card-img-top,
.card-img-bottom, .card-img-bottom,
.card-header, .card-header,
.card-footer { .card-footer {
@include border-radius(0); @include border-radius(0);
} }
} }
} }
} }
} }
} }
// //
// Columns // Columns
// //
.card-columns { .card-columns {
.card { .card {
margin-bottom: $card-columns-margin; margin-bottom: $card-columns-margin;
} }
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
column-count: $card-columns-count; column-count: $card-columns-count;
column-gap: $card-columns-gap; column-gap: $card-columns-gap;
orphans: 1; orphans: 1;
widows: 1; widows: 1;
.card { .card {
display: inline-block; // Don't let them vertically span multiple columns display: inline-block; // Don't let them vertically span multiple columns
width: 100%; // Don't let their width change width: 100%; // Don't let their width change
} }
} }
} }
// //
// Accordion // Accordion
// //
.accordion { .accordion {
.card:not(:first-of-type):not(:last-of-type) { .card:not(:first-of-type):not(:last-of-type) {
border-bottom: 0; border-bottom: 0;
border-radius: 0; border-radius: 0;
} }
.card:not(:first-of-type) { .card:not(:first-of-type) {
.card-header:first-child { .card-header:first-child {
border-radius: 0; border-radius: 0;
} }
} }
.card:first-of-type { .card:first-of-type {
border-bottom: 0; border-bottom: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
} }
.card:last-of-type { .card:last-of-type {
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
} }
} }

View File

@@ -1,236 +1,236 @@
// Notes on the classes: // Notes on the classes:
// //
// 1. The .carousel-item-left and .carousel-item-right is used to indicate where // 1. The .carousel-item-left and .carousel-item-right is used to indicate where
// the active slide is heading. // the active slide is heading.
// 2. .active.carousel-item is the current slide. // 2. .active.carousel-item is the current slide.
// 3. .active.carousel-item-left and .active.carousel-item-right is the current // 3. .active.carousel-item-left and .active.carousel-item-right is the current
// slide in its in-transition state. Only one of these occurs at a time. // slide in its in-transition state. Only one of these occurs at a time.
// 4. .carousel-item-next.carousel-item-left and .carousel-item-prev.carousel-item-right // 4. .carousel-item-next.carousel-item-left and .carousel-item-prev.carousel-item-right
// is the upcoming slide in transition. // is the upcoming slide in transition.
.carousel { .carousel {
position: relative; position: relative;
} }
.carousel-inner { .carousel-inner {
position: relative; position: relative;
width: 100%; width: 100%;
overflow: hidden; overflow: hidden;
} }
.carousel-item { .carousel-item {
position: relative; position: relative;
display: none; display: none;
align-items: center; align-items: center;
width: 100%; width: 100%;
@include transition($carousel-transition); @include transition($carousel-transition);
backface-visibility: hidden; backface-visibility: hidden;
perspective: 1000px; perspective: 1000px;
} }
.carousel-item.active, .carousel-item.active,
.carousel-item-next, .carousel-item-next,
.carousel-item-prev { .carousel-item-prev {
display: block; display: block;
} }
.carousel-item-next, .carousel-item-next,
.carousel-item-prev { .carousel-item-prev {
position: absolute; position: absolute;
top: 0; top: 0;
} }
.carousel-item-next.carousel-item-left, .carousel-item-next.carousel-item-left,
.carousel-item-prev.carousel-item-right { .carousel-item-prev.carousel-item-right {
transform: translateX(0); transform: translateX(0);
@supports (transform-style: preserve-3d) { @supports (transform-style: preserve-3d) {
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
} }
.carousel-item-next, .carousel-item-next,
.active.carousel-item-right { .active.carousel-item-right {
transform: translateX(100%); transform: translateX(100%);
@supports (transform-style: preserve-3d) { @supports (transform-style: preserve-3d) {
transform: translate3d(100%, 0, 0); transform: translate3d(100%, 0, 0);
} }
} }
.carousel-item-prev, .carousel-item-prev,
.active.carousel-item-left { .active.carousel-item-left {
transform: translateX(-100%); transform: translateX(-100%);
@supports (transform-style: preserve-3d) { @supports (transform-style: preserve-3d) {
transform: translate3d(-100%, 0, 0); transform: translate3d(-100%, 0, 0);
} }
} }
// //
// Alternate transitions // Alternate transitions
// //
.carousel-fade { .carousel-fade {
.carousel-item { .carousel-item {
opacity: 0; opacity: 0;
transition-duration: .6s; transition-duration: .6s;
transition-property: opacity; transition-property: opacity;
} }
.carousel-item.active, .carousel-item.active,
.carousel-item-next.carousel-item-left, .carousel-item-next.carousel-item-left,
.carousel-item-prev.carousel-item-right { .carousel-item-prev.carousel-item-right {
opacity: 1; opacity: 1;
} }
.active.carousel-item-left, .active.carousel-item-left,
.active.carousel-item-right { .active.carousel-item-right {
opacity: 0; opacity: 0;
} }
.carousel-item-next, .carousel-item-next,
.carousel-item-prev, .carousel-item-prev,
.carousel-item.active, .carousel-item.active,
.active.carousel-item-left, .active.carousel-item-left,
.active.carousel-item-prev { .active.carousel-item-prev {
transform: translateX(0); transform: translateX(0);
@supports (transform-style: preserve-3d) { @supports (transform-style: preserve-3d) {
transform: translate3d(0, 0, 0); transform: translate3d(0, 0, 0);
} }
} }
} }
// //
// Left/right controls for nav // Left/right controls for nav
// //
.carousel-control-prev, .carousel-control-prev,
.carousel-control-next { .carousel-control-next {
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
// Use flex for alignment (1-3) // Use flex for alignment (1-3)
display: flex; // 1. allow flex styles display: flex; // 1. allow flex styles
align-items: center; // 2. vertically center contents align-items: center; // 2. vertically center contents
justify-content: center; // 3. horizontally center contents justify-content: center; // 3. horizontally center contents
width: $carousel-control-width; width: $carousel-control-width;
color: $carousel-control-color; color: $carousel-control-color;
text-align: center; text-align: center;
opacity: $carousel-control-opacity; opacity: $carousel-control-opacity;
// We can't have a transition here because WebKit cancels the carousel // We can't have a transition here because WebKit cancels the carousel
// animation if you trip this while in the middle of another animation. // animation if you trip this while in the middle of another animation.
// Hover/focus state // Hover/focus state
@include hover-focus { @include hover-focus {
color: $carousel-control-color; color: $carousel-control-color;
text-decoration: none; text-decoration: none;
outline: 0; outline: 0;
opacity: .9; opacity: .9;
} }
} }
.carousel-control-prev { .carousel-control-prev {
left: 0; left: 0;
@if $enable-gradients { @if $enable-gradients {
background: linear-gradient(90deg, rgba($black, .25), rgba($black, .001)); background: linear-gradient(90deg, rgba($black, .25), rgba($black, .001));
} }
} }
.carousel-control-next { .carousel-control-next {
right: 0; right: 0;
@if $enable-gradients { @if $enable-gradients {
background: linear-gradient(270deg, rgba($black, .25), rgba($black, .001)); background: linear-gradient(270deg, rgba($black, .25), rgba($black, .001));
} }
} }
// Icons for within // Icons for within
.carousel-control-prev-icon, .carousel-control-prev-icon,
.carousel-control-next-icon { .carousel-control-next-icon {
display: inline-block; display: inline-block;
width: $carousel-control-icon-width; width: $carousel-control-icon-width;
height: $carousel-control-icon-width; height: $carousel-control-icon-width;
background: transparent no-repeat center center; background: transparent no-repeat center center;
background-size: 100% 100%; background-size: 100% 100%;
} }
.carousel-control-prev-icon { .carousel-control-prev-icon {
background-image: $carousel-control-prev-icon-bg; background-image: $carousel-control-prev-icon-bg;
} }
.carousel-control-next-icon { .carousel-control-next-icon {
background-image: $carousel-control-next-icon-bg; background-image: $carousel-control-next-icon-bg;
} }
// Optional indicator pips // Optional indicator pips
// //
// Add an ordered list with the following class and add a list item for each // Add an ordered list with the following class and add a list item for each
// slide your carousel holds. // slide your carousel holds.
.carousel-indicators { .carousel-indicators {
position: absolute; position: absolute;
right: 0; right: 0;
bottom: 10px; bottom: 10px;
left: 0; left: 0;
z-index: 15; z-index: 15;
display: flex; display: flex;
justify-content: center; justify-content: center;
padding-left: 0; // override <ol> default padding-left: 0; // override <ol> default
// Use the .carousel-control's width as margin so we don't overlay those // Use the .carousel-control's width as margin so we don't overlay those
margin-right: $carousel-control-width; margin-right: $carousel-control-width;
margin-left: $carousel-control-width; margin-left: $carousel-control-width;
list-style: none; list-style: none;
li { li {
position: relative; position: relative;
flex: 0 1 auto; flex: 0 1 auto;
width: $carousel-indicator-width; width: $carousel-indicator-width;
height: $carousel-indicator-height; height: $carousel-indicator-height;
margin-right: $carousel-indicator-spacer; margin-right: $carousel-indicator-spacer;
margin-left: $carousel-indicator-spacer; margin-left: $carousel-indicator-spacer;
text-indent: -999px; text-indent: -999px;
cursor: pointer; cursor: pointer;
background-color: rgba($carousel-indicator-active-bg, .5); background-color: rgba($carousel-indicator-active-bg, .5);
// Use pseudo classes to increase the hit area by 10px on top and bottom. // Use pseudo classes to increase the hit area by 10px on top and bottom.
&::before { &::before {
position: absolute; position: absolute;
top: -10px; top: -10px;
left: 0; left: 0;
display: inline-block; display: inline-block;
width: 100%; width: 100%;
height: 10px; height: 10px;
content: ""; content: "";
} }
&::after { &::after {
position: absolute; position: absolute;
bottom: -10px; bottom: -10px;
left: 0; left: 0;
display: inline-block; display: inline-block;
width: 100%; width: 100%;
height: 10px; height: 10px;
content: ""; content: "";
} }
} }
.active { .active {
background-color: $carousel-indicator-active-bg; background-color: $carousel-indicator-active-bg;
} }
} }
// Optional captions // Optional captions
// //
// //
.carousel-caption { .carousel-caption {
position: absolute; position: absolute;
right: ((100% - $carousel-caption-width) / 2); right: ((100% - $carousel-caption-width) / 2);
bottom: 20px; bottom: 20px;
left: ((100% - $carousel-caption-width) / 2); left: ((100% - $carousel-caption-width) / 2);
z-index: 10; z-index: 10;
padding-top: 20px; padding-top: 20px;
padding-bottom: 20px; padding-bottom: 20px;
color: $carousel-caption-color; color: $carousel-caption-color;
text-align: center; text-align: center;
} }

View File

@@ -1,34 +1,34 @@
.close { .close {
float: right; float: right;
font-size: $close-font-size; font-size: $close-font-size;
font-weight: $close-font-weight; font-weight: $close-font-weight;
line-height: 1; line-height: 1;
color: $close-color; color: $close-color;
text-shadow: $close-text-shadow; text-shadow: $close-text-shadow;
opacity: .5; opacity: .5;
@include hover-focus { @include hover-focus {
color: $close-color; color: $close-color;
text-decoration: none; text-decoration: none;
opacity: .75; opacity: .75;
} }
// Opinionated: add "hand" cursor to non-disabled .close elements // Opinionated: add "hand" cursor to non-disabled .close elements
&:not(:disabled):not(.disabled) { &:not(:disabled):not(.disabled) {
cursor: pointer; cursor: pointer;
} }
} }
// Additional properties for button version // Additional properties for button version
// iOS requires the button element instead of an anchor tag. // iOS requires the button element instead of an anchor tag.
// If you want the anchor version, it requires `href="#"`. // If you want the anchor version, it requires `href="#"`.
// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
// stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type // stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type
button.close { button.close {
padding: 0; padding: 0;
background-color: transparent; background-color: transparent;
border: 0; border: 0;
-webkit-appearance: none; -webkit-appearance: none;
} }
// stylelint-enable // stylelint-enable

View File

@@ -1,48 +1,48 @@
// Inline code // Inline code
code { code {
font-size: $code-font-size; font-size: $code-font-size;
color: $code-color; color: $code-color;
word-break: break-word; word-break: break-word;
// Streamline the style when inside anchors to avoid broken underline and more // Streamline the style when inside anchors to avoid broken underline and more
a > & { a > & {
color: inherit; color: inherit;
} }
} }
// User input typically entered via keyboard // User input typically entered via keyboard
kbd { kbd {
padding: $kbd-padding-y $kbd-padding-x; padding: $kbd-padding-y $kbd-padding-x;
font-size: $kbd-font-size; font-size: $kbd-font-size;
color: $kbd-color; color: $kbd-color;
background-color: $kbd-bg; background-color: $kbd-bg;
@include border-radius($border-radius-sm); @include border-radius($border-radius-sm);
@include box-shadow($kbd-box-shadow); @include box-shadow($kbd-box-shadow);
kbd { kbd {
padding: 0; padding: 0;
font-size: 100%; font-size: 100%;
font-weight: $nested-kbd-font-weight; font-weight: $nested-kbd-font-weight;
@include box-shadow(none); @include box-shadow(none);
} }
} }
// Blocks of code // Blocks of code
pre { pre {
display: block; display: block;
font-size: $code-font-size; font-size: $code-font-size;
color: $pre-color; color: $pre-color;
// Account for some code outputs that place code tags in pre tags // Account for some code outputs that place code tags in pre tags
code { code {
font-size: inherit; font-size: inherit;
color: inherit; color: inherit;
word-break: normal; word-break: normal;
} }
} }
// Enable scrollable blocks of code // Enable scrollable blocks of code
.pre-scrollable { .pre-scrollable {
max-height: $pre-scrollable-max-height; max-height: $pre-scrollable-max-height;
overflow-y: scroll; overflow-y: scroll;
} }

View File

@@ -1,421 +1,421 @@
// Embedded icons from Open Iconic. // Embedded icons from Open Iconic.
// Released under MIT and copyright 2014 Waybury. // Released under MIT and copyright 2014 Waybury.
// https://useiconic.com/open // https://useiconic.com/open
// Checkboxes and radios // Checkboxes and radios
// //
// Base class takes care of all the key behavioral aspects. // Base class takes care of all the key behavioral aspects.
.custom-control { .custom-control {
position: relative; position: relative;
display: block; display: block;
min-height: (1rem * $line-height-base); min-height: (1rem * $line-height-base);
padding-left: $custom-control-gutter; padding-left: $custom-control-gutter;
} }
.custom-control-inline { .custom-control-inline {
display: inline-flex; display: inline-flex;
margin-right: $custom-control-spacer-x; margin-right: $custom-control-spacer-x;
} }
.custom-control-input { .custom-control-input {
position: absolute; position: absolute;
z-index: -1; // Put the input behind the label so it doesn't overlay text z-index: -1; // Put the input behind the label so it doesn't overlay text
opacity: 0; opacity: 0;
&:checked ~ .custom-control-label::before { &:checked ~ .custom-control-label::before {
color: $custom-control-indicator-checked-color; color: $custom-control-indicator-checked-color;
@include gradient-bg($custom-control-indicator-checked-bg); @include gradient-bg($custom-control-indicator-checked-bg);
@include box-shadow($custom-control-indicator-checked-box-shadow); @include box-shadow($custom-control-indicator-checked-box-shadow);
} }
&:focus ~ .custom-control-label::before { &:focus ~ .custom-control-label::before {
// the mixin is not used here to make sure there is feedback // the mixin is not used here to make sure there is feedback
box-shadow: $custom-control-indicator-focus-box-shadow; box-shadow: $custom-control-indicator-focus-box-shadow;
} }
&:active ~ .custom-control-label::before { &:active ~ .custom-control-label::before {
color: $custom-control-indicator-active-color; color: $custom-control-indicator-active-color;
background-color: $custom-control-indicator-active-bg; background-color: $custom-control-indicator-active-bg;
@include box-shadow($custom-control-indicator-active-box-shadow); @include box-shadow($custom-control-indicator-active-box-shadow);
} }
&:disabled { &:disabled {
~ .custom-control-label { ~ .custom-control-label {
color: $custom-control-label-disabled-color; color: $custom-control-label-disabled-color;
&::before { &::before {
background-color: $custom-control-indicator-disabled-bg; background-color: $custom-control-indicator-disabled-bg;
} }
} }
} }
} }
// Custom control indicators // Custom control indicators
// //
// Build the custom controls out of pseudo-elements. // Build the custom controls out of pseudo-elements.
.custom-control-label { .custom-control-label {
position: relative; position: relative;
margin-bottom: 0; margin-bottom: 0;
// Background-color and (when enabled) gradient // Background-color and (when enabled) gradient
&::before { &::before {
position: absolute; position: absolute;
top: (($line-height-base - $custom-control-indicator-size) / 2); top: (($line-height-base - $custom-control-indicator-size) / 2);
left: -$custom-control-gutter; left: -$custom-control-gutter;
display: block; display: block;
width: $custom-control-indicator-size; width: $custom-control-indicator-size;
height: $custom-control-indicator-size; height: $custom-control-indicator-size;
pointer-events: none; pointer-events: none;
content: ""; content: "";
user-select: none; user-select: none;
background-color: $custom-control-indicator-bg; background-color: $custom-control-indicator-bg;
@include box-shadow($custom-control-indicator-box-shadow); @include box-shadow($custom-control-indicator-box-shadow);
} }
// Foreground (icon) // Foreground (icon)
&::after { &::after {
position: absolute; position: absolute;
top: (($line-height-base - $custom-control-indicator-size) / 2); top: (($line-height-base - $custom-control-indicator-size) / 2);
left: -$custom-control-gutter; left: -$custom-control-gutter;
display: block; display: block;
width: $custom-control-indicator-size; width: $custom-control-indicator-size;
height: $custom-control-indicator-size; height: $custom-control-indicator-size;
content: ""; content: "";
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center center; background-position: center center;
background-size: $custom-control-indicator-bg-size; background-size: $custom-control-indicator-bg-size;
} }
} }
// Checkboxes // Checkboxes
// //
// Tweak just a few things for checkboxes. // Tweak just a few things for checkboxes.
.custom-checkbox { .custom-checkbox {
.custom-control-label::before { .custom-control-label::before {
@include border-radius($custom-checkbox-indicator-border-radius); @include border-radius($custom-checkbox-indicator-border-radius);
} }
.custom-control-input:checked ~ .custom-control-label { .custom-control-input:checked ~ .custom-control-label {
&::before { &::before {
@include gradient-bg($custom-control-indicator-checked-bg); @include gradient-bg($custom-control-indicator-checked-bg);
} }
&::after { &::after {
background-image: $custom-checkbox-indicator-icon-checked; background-image: $custom-checkbox-indicator-icon-checked;
} }
} }
.custom-control-input:indeterminate ~ .custom-control-label { .custom-control-input:indeterminate ~ .custom-control-label {
&::before { &::before {
@include gradient-bg($custom-checkbox-indicator-indeterminate-bg); @include gradient-bg($custom-checkbox-indicator-indeterminate-bg);
@include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow); @include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow);
} }
&::after { &::after {
background-image: $custom-checkbox-indicator-icon-indeterminate; background-image: $custom-checkbox-indicator-icon-indeterminate;
} }
} }
.custom-control-input:disabled { .custom-control-input:disabled {
&:checked ~ .custom-control-label::before { &:checked ~ .custom-control-label::before {
background-color: $custom-control-indicator-checked-disabled-bg; background-color: $custom-control-indicator-checked-disabled-bg;
} }
&:indeterminate ~ .custom-control-label::before { &:indeterminate ~ .custom-control-label::before {
background-color: $custom-control-indicator-checked-disabled-bg; background-color: $custom-control-indicator-checked-disabled-bg;
} }
} }
} }
// Radios // Radios
// //
// Tweak just a few things for radios. // Tweak just a few things for radios.
.custom-radio { .custom-radio {
.custom-control-label::before { .custom-control-label::before {
border-radius: $custom-radio-indicator-border-radius; border-radius: $custom-radio-indicator-border-radius;
} }
.custom-control-input:checked ~ .custom-control-label { .custom-control-input:checked ~ .custom-control-label {
&::before { &::before {
@include gradient-bg($custom-control-indicator-checked-bg); @include gradient-bg($custom-control-indicator-checked-bg);
} }
&::after { &::after {
background-image: $custom-radio-indicator-icon-checked; background-image: $custom-radio-indicator-icon-checked;
} }
} }
.custom-control-input:disabled { .custom-control-input:disabled {
&:checked ~ .custom-control-label::before { &:checked ~ .custom-control-label::before {
background-color: $custom-control-indicator-checked-disabled-bg; background-color: $custom-control-indicator-checked-disabled-bg;
} }
} }
} }
// Select // Select
// //
// Replaces the browser default select with a custom one, mostly pulled from // Replaces the browser default select with a custom one, mostly pulled from
// https://primer.github.io/. // https://primer.github.io/.
// //
.custom-select { .custom-select {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
height: $custom-select-height; height: $custom-select-height;
padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x; padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x;
line-height: $custom-select-line-height; line-height: $custom-select-line-height;
color: $custom-select-color; color: $custom-select-color;
vertical-align: middle; vertical-align: middle;
background: $custom-select-bg $custom-select-indicator no-repeat right $custom-select-padding-x center; background: $custom-select-bg $custom-select-indicator no-repeat right $custom-select-padding-x center;
background-size: $custom-select-bg-size; background-size: $custom-select-bg-size;
border: $custom-select-border-width solid $custom-select-border-color; border: $custom-select-border-width solid $custom-select-border-color;
@if $enable-rounded { @if $enable-rounded {
border-radius: $custom-select-border-radius; border-radius: $custom-select-border-radius;
} @else { } @else {
border-radius: 0; border-radius: 0;
} }
appearance: none; appearance: none;
&:focus { &:focus {
border-color: $custom-select-focus-border-color; border-color: $custom-select-focus-border-color;
outline: 0; outline: 0;
box-shadow: $custom-select-focus-box-shadow; box-shadow: $custom-select-focus-box-shadow;
&::-ms-value { &::-ms-value {
// For visual consistency with other platforms/browsers, // For visual consistency with other platforms/browsers,
// suppress the default white text on blue background highlight given to // suppress the default white text on blue background highlight given to
// the selected option text when the (still closed) <select> receives focus // the selected option text when the (still closed) <select> receives focus
// in IE and (under certain conditions) Edge. // in IE and (under certain conditions) Edge.
// See https://github.com/twbs/bootstrap/issues/19398. // See https://github.com/twbs/bootstrap/issues/19398.
color: $input-color; color: $input-color;
background-color: $input-bg; background-color: $input-bg;
} }
} }
&[multiple], &[multiple],
&[size]:not([size="1"]) { &[size]:not([size="1"]) {
height: auto; height: auto;
padding-right: $custom-select-padding-x; padding-right: $custom-select-padding-x;
background-image: none; background-image: none;
} }
&:disabled { &:disabled {
color: $custom-select-disabled-color; color: $custom-select-disabled-color;
background-color: $custom-select-disabled-bg; background-color: $custom-select-disabled-bg;
} }
// Hides the default caret in IE11 // Hides the default caret in IE11
&::-ms-expand { &::-ms-expand {
opacity: 0; opacity: 0;
} }
} }
.custom-select-sm { .custom-select-sm {
height: $custom-select-height-sm; height: $custom-select-height-sm;
padding-top: $custom-select-padding-y; padding-top: $custom-select-padding-y;
padding-bottom: $custom-select-padding-y; padding-bottom: $custom-select-padding-y;
font-size: $custom-select-font-size-sm; font-size: $custom-select-font-size-sm;
} }
.custom-select-lg { .custom-select-lg {
height: $custom-select-height-lg; height: $custom-select-height-lg;
padding-top: $custom-select-padding-y; padding-top: $custom-select-padding-y;
padding-bottom: $custom-select-padding-y; padding-bottom: $custom-select-padding-y;
font-size: $custom-select-font-size-lg; font-size: $custom-select-font-size-lg;
} }
// File // File
// //
// Custom file input. // Custom file input.
.custom-file { .custom-file {
position: relative; position: relative;
display: inline-block; display: inline-block;
width: 100%; width: 100%;
height: $custom-file-height; height: $custom-file-height;
margin-bottom: 0; margin-bottom: 0;
} }
.custom-file-input { .custom-file-input {
position: relative; position: relative;
z-index: 2; z-index: 2;
width: 100%; width: 100%;
height: $custom-file-height; height: $custom-file-height;
margin: 0; margin: 0;
opacity: 0; opacity: 0;
&:focus ~ .custom-file-label { &:focus ~ .custom-file-label {
border-color: $custom-file-focus-border-color; border-color: $custom-file-focus-border-color;
box-shadow: $custom-file-focus-box-shadow; box-shadow: $custom-file-focus-box-shadow;
&::after { &::after {
border-color: $custom-file-focus-border-color; border-color: $custom-file-focus-border-color;
} }
} }
@each $lang, $value in $custom-file-text { @each $lang, $value in $custom-file-text {
&:lang(#{$lang}) ~ .custom-file-label::after { &:lang(#{$lang}) ~ .custom-file-label::after {
content: $value; content: $value;
} }
} }
} }
.custom-file-label { .custom-file-label {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
left: 0; left: 0;
z-index: 1; z-index: 1;
height: $custom-file-height; height: $custom-file-height;
padding: $custom-file-padding-y $custom-file-padding-x; padding: $custom-file-padding-y $custom-file-padding-x;
line-height: $custom-file-line-height; line-height: $custom-file-line-height;
color: $custom-file-color; color: $custom-file-color;
background-color: $custom-file-bg; background-color: $custom-file-bg;
border: $custom-file-border-width solid $custom-file-border-color; border: $custom-file-border-width solid $custom-file-border-color;
@include border-radius($custom-file-border-radius); @include border-radius($custom-file-border-radius);
@include box-shadow($custom-file-box-shadow); @include box-shadow($custom-file-box-shadow);
&::after { &::after {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
z-index: 3; z-index: 3;
display: block; display: block;
height: $custom-file-height-inner; height: $custom-file-height-inner;
padding: $custom-file-padding-y $custom-file-padding-x; padding: $custom-file-padding-y $custom-file-padding-x;
line-height: $custom-file-line-height; line-height: $custom-file-line-height;
color: $custom-file-button-color; color: $custom-file-button-color;
content: "Browse"; content: "Browse";
@include gradient-bg($custom-file-button-bg); @include gradient-bg($custom-file-button-bg);
border-left: $custom-file-border-width solid $custom-file-border-color; border-left: $custom-file-border-width solid $custom-file-border-color;
@include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0); @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0);
} }
} }
// Range // Range
// //
// Style range inputs the same across browsers. Vendor-specific rules for pseudo // Style range inputs the same across browsers. Vendor-specific rules for pseudo
// elements cannot be mixed. As such, there are no shared styles for focus or // elements cannot be mixed. As such, there are no shared styles for focus or
// active states on prefixed selectors. // active states on prefixed selectors.
.custom-range { .custom-range {
width: 100%; width: 100%;
padding-left: 0; // Firefox specific padding-left: 0; // Firefox specific
background-color: transparent; background-color: transparent;
appearance: none; appearance: none;
&:focus { &:focus {
outline: none; outline: none;
} }
&::-moz-focus-outer { &::-moz-focus-outer {
border: 0; border: 0;
} }
&::-webkit-slider-thumb { &::-webkit-slider-thumb {
width: $custom-range-thumb-width; width: $custom-range-thumb-width;
height: $custom-range-thumb-height; height: $custom-range-thumb-height;
margin-top: -($custom-range-thumb-width * .25); // Webkit specific? margin-top: -($custom-range-thumb-width * .25); // Webkit specific?
@include gradient-bg($custom-range-thumb-bg); @include gradient-bg($custom-range-thumb-bg);
border: $custom-range-thumb-border; border: $custom-range-thumb-border;
@include border-radius($custom-range-thumb-border-radius); @include border-radius($custom-range-thumb-border-radius);
@include box-shadow($custom-range-thumb-box-shadow); @include box-shadow($custom-range-thumb-box-shadow);
appearance: none; appearance: none;
&:focus { &:focus {
outline: none; outline: none;
box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility
} }
&:active { &:active {
@include gradient-bg($custom-range-thumb-active-bg); @include gradient-bg($custom-range-thumb-active-bg);
} }
} }
&::-webkit-slider-runnable-track { &::-webkit-slider-runnable-track {
width: $custom-range-track-width; width: $custom-range-track-width;
height: $custom-range-track-height; height: $custom-range-track-height;
color: transparent; // Why? color: transparent; // Why?
cursor: $custom-range-track-cursor; cursor: $custom-range-track-cursor;
background-color: $custom-range-track-bg; background-color: $custom-range-track-bg;
border-color: transparent; border-color: transparent;
@include border-radius($custom-range-track-border-radius); @include border-radius($custom-range-track-border-radius);
@include box-shadow($custom-range-track-box-shadow); @include box-shadow($custom-range-track-box-shadow);
} }
&::-moz-range-thumb { &::-moz-range-thumb {
width: $custom-range-thumb-width; width: $custom-range-thumb-width;
height: $custom-range-thumb-height; height: $custom-range-thumb-height;
@include gradient-bg($custom-range-thumb-bg); @include gradient-bg($custom-range-thumb-bg);
border: $custom-range-thumb-border; border: $custom-range-thumb-border;
@include border-radius($custom-range-thumb-border-radius); @include border-radius($custom-range-thumb-border-radius);
@include box-shadow($custom-range-thumb-box-shadow); @include box-shadow($custom-range-thumb-box-shadow);
appearance: none; appearance: none;
&:focus { &:focus {
outline: none; outline: none;
box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility
} }
&:active { &:active {
@include gradient-bg($custom-range-thumb-active-bg); @include gradient-bg($custom-range-thumb-active-bg);
} }
} }
&::-moz-range-track { &::-moz-range-track {
width: $custom-range-track-width; width: $custom-range-track-width;
height: $custom-range-track-height; height: $custom-range-track-height;
color: transparent; color: transparent;
cursor: $custom-range-track-cursor; cursor: $custom-range-track-cursor;
background-color: $custom-range-track-bg; background-color: $custom-range-track-bg;
border-color: transparent; // Firefox specific? border-color: transparent; // Firefox specific?
@include border-radius($custom-range-track-border-radius); @include border-radius($custom-range-track-border-radius);
@include box-shadow($custom-range-track-box-shadow); @include box-shadow($custom-range-track-box-shadow);
} }
&::-ms-thumb { &::-ms-thumb {
width: $custom-range-thumb-width; width: $custom-range-thumb-width;
height: $custom-range-thumb-height; height: $custom-range-thumb-height;
@include gradient-bg($custom-range-thumb-bg); @include gradient-bg($custom-range-thumb-bg);
border: $custom-range-thumb-border; border: $custom-range-thumb-border;
@include border-radius($custom-range-thumb-border-radius); @include border-radius($custom-range-thumb-border-radius);
@include box-shadow($custom-range-thumb-box-shadow); @include box-shadow($custom-range-thumb-box-shadow);
appearance: none; appearance: none;
&:focus { &:focus {
outline: none; outline: none;
box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility box-shadow: $custom-range-thumb-focus-box-shadow; // No mixin for focus accessibility
} }
&:active { &:active {
@include gradient-bg($custom-range-thumb-active-bg); @include gradient-bg($custom-range-thumb-active-bg);
} }
} }
&::-ms-track { &::-ms-track {
width: $custom-range-track-width; width: $custom-range-track-width;
height: $custom-range-track-height; height: $custom-range-track-height;
color: transparent; color: transparent;
cursor: $custom-range-track-cursor; cursor: $custom-range-track-cursor;
background-color: transparent; background-color: transparent;
border-color: transparent; border-color: transparent;
border-width: ($custom-range-thumb-height * .5); border-width: ($custom-range-thumb-height * .5);
@include box-shadow($custom-range-track-box-shadow); @include box-shadow($custom-range-track-box-shadow);
} }
&::-ms-fill-lower { &::-ms-fill-lower {
background-color: $custom-range-track-bg; background-color: $custom-range-track-bg;
@include border-radius($custom-range-track-border-radius); @include border-radius($custom-range-track-border-radius);
} }
&::-ms-fill-upper { &::-ms-fill-upper {
margin-right: 15px; // arbitrary? margin-right: 15px; // arbitrary?
background-color: $custom-range-track-bg; background-color: $custom-range-track-bg;
@include border-radius($custom-range-track-border-radius); @include border-radius($custom-range-track-border-radius);
} }
} }

View File

@@ -1,166 +1,166 @@
// The dropdown wrapper (`<div>`) // The dropdown wrapper (`<div>`)
.dropup, .dropup,
.dropright, .dropright,
.dropdown, .dropdown,
.dropleft { .dropleft {
position: relative; position: relative;
} }
.dropdown-toggle { .dropdown-toggle {
// Generate the caret automatically // Generate the caret automatically
@include caret; @include caret;
} }
// The dropdown menu // The dropdown menu
.dropdown-menu { .dropdown-menu {
position: absolute; position: absolute;
top: 100%; top: 100%;
left: 0; left: 0;
z-index: $zindex-dropdown; z-index: $zindex-dropdown;
display: none; // none by default, but block on "open" of the menu display: none; // none by default, but block on "open" of the menu
float: left; float: left;
min-width: $dropdown-min-width; min-width: $dropdown-min-width;
padding: $dropdown-padding-y 0; padding: $dropdown-padding-y 0;
margin: $dropdown-spacer 0 0; // override default ul margin: $dropdown-spacer 0 0; // override default ul
font-size: $font-size-base; // Redeclare because nesting can cause inheritance issues font-size: $font-size-base; // Redeclare because nesting can cause inheritance issues
color: $body-color; color: $body-color;
text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer) text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)
list-style: none; list-style: none;
background-color: $dropdown-bg; background-color: $dropdown-bg;
background-clip: padding-box; background-clip: padding-box;
border: $dropdown-border-width solid $dropdown-border-color; border: $dropdown-border-width solid $dropdown-border-color;
@include border-radius($dropdown-border-radius); @include border-radius($dropdown-border-radius);
@include box-shadow($dropdown-box-shadow); @include box-shadow($dropdown-box-shadow);
} }
.dropdown-menu-right { .dropdown-menu-right {
right: 0; right: 0;
left: auto; left: auto;
} }
// Allow for dropdowns to go bottom up (aka, dropup-menu) // Allow for dropdowns to go bottom up (aka, dropup-menu)
// Just add .dropup after the standard .dropdown class and you're set. // Just add .dropup after the standard .dropdown class and you're set.
.dropup { .dropup {
.dropdown-menu { .dropdown-menu {
top: auto; top: auto;
bottom: 100%; bottom: 100%;
margin-top: 0; margin-top: 0;
margin-bottom: $dropdown-spacer; margin-bottom: $dropdown-spacer;
} }
.dropdown-toggle { .dropdown-toggle {
@include caret(up); @include caret(up);
} }
} }
.dropright { .dropright {
.dropdown-menu { .dropdown-menu {
top: 0; top: 0;
right: auto; right: auto;
left: 100%; left: 100%;
margin-top: 0; margin-top: 0;
margin-left: $dropdown-spacer; margin-left: $dropdown-spacer;
} }
.dropdown-toggle { .dropdown-toggle {
@include caret(right); @include caret(right);
&::after { &::after {
vertical-align: 0; vertical-align: 0;
} }
} }
} }
.dropleft { .dropleft {
.dropdown-menu { .dropdown-menu {
top: 0; top: 0;
right: 100%; right: 100%;
left: auto; left: auto;
margin-top: 0; margin-top: 0;
margin-right: $dropdown-spacer; margin-right: $dropdown-spacer;
} }
.dropdown-toggle { .dropdown-toggle {
@include caret(left); @include caret(left);
&::before { &::before {
vertical-align: 0; vertical-align: 0;
} }
} }
} }
// When enabled Popper.js, reset basic dropdown position // When enabled Popper.js, reset basic dropdown position
// stylelint-disable no-duplicate-selectors // stylelint-disable no-duplicate-selectors
.dropdown-menu { .dropdown-menu {
&[x-placement^="top"], &[x-placement^="top"],
&[x-placement^="right"], &[x-placement^="right"],
&[x-placement^="bottom"], &[x-placement^="bottom"],
&[x-placement^="left"] { &[x-placement^="left"] {
right: auto; right: auto;
bottom: auto; bottom: auto;
} }
} }
// stylelint-enable no-duplicate-selectors // stylelint-enable no-duplicate-selectors
// Dividers (basically an `<hr>`) within the dropdown // Dividers (basically an `<hr>`) within the dropdown
.dropdown-divider { .dropdown-divider {
@include nav-divider($dropdown-divider-bg); @include nav-divider($dropdown-divider-bg);
} }
// Links, buttons, and more within the dropdown menu // Links, buttons, and more within the dropdown menu
// //
// `<button>`-specific styles are denoted with `// For <button>s` // `<button>`-specific styles are denoted with `// For <button>s`
.dropdown-item { .dropdown-item {
display: block; display: block;
width: 100%; // For `<button>`s width: 100%; // For `<button>`s
padding: $dropdown-item-padding-y $dropdown-item-padding-x; padding: $dropdown-item-padding-y $dropdown-item-padding-x;
clear: both; clear: both;
font-weight: $font-weight-normal; font-weight: $font-weight-normal;
color: $dropdown-link-color; color: $dropdown-link-color;
text-align: inherit; // For `<button>`s text-align: inherit; // For `<button>`s
white-space: nowrap; // prevent links from randomly breaking onto new lines white-space: nowrap; // prevent links from randomly breaking onto new lines
background-color: transparent; // For `<button>`s background-color: transparent; // For `<button>`s
border: 0; // For `<button>`s border: 0; // For `<button>`s
@include hover-focus { @include hover-focus {
color: $dropdown-link-hover-color; color: $dropdown-link-hover-color;
text-decoration: none; text-decoration: none;
@include gradient-bg($dropdown-link-hover-bg); @include gradient-bg($dropdown-link-hover-bg);
} }
&.active, &.active,
&:active { &:active {
color: $dropdown-link-active-color; color: $dropdown-link-active-color;
text-decoration: none; text-decoration: none;
@include gradient-bg($dropdown-link-active-bg); @include gradient-bg($dropdown-link-active-bg);
} }
&.disabled, &.disabled,
&:disabled { &:disabled {
color: $dropdown-link-disabled-color; color: $dropdown-link-disabled-color;
background-color: transparent; background-color: transparent;
// Remove CSS gradients if they're enabled // Remove CSS gradients if they're enabled
@if $enable-gradients { @if $enable-gradients {
background-image: none; background-image: none;
} }
} }
} }
.dropdown-menu.show { .dropdown-menu.show {
display: block; display: block;
} }
// Dropdown section headers // Dropdown section headers
.dropdown-header { .dropdown-header {
display: block; display: block;
padding: $dropdown-padding-y $dropdown-item-padding-x; padding: $dropdown-padding-y $dropdown-item-padding-x;
margin-bottom: 0; // for use with heading elements margin-bottom: 0; // for use with heading elements
font-size: $font-size-sm; font-size: $font-size-sm;
color: $dropdown-header-color; color: $dropdown-header-color;
white-space: nowrap; // as with > li > a white-space: nowrap; // as with > li > a
} }
// Dropdown text // Dropdown text
.dropdown-item-text { .dropdown-item-text {
display: block; display: block;
padding: $dropdown-item-padding-y $dropdown-item-padding-x; padding: $dropdown-item-padding-y $dropdown-item-padding-x;
color: $dropdown-link-color; color: $dropdown-link-color;
} }

View File

@@ -1,335 +1,335 @@
// stylelint-disable selector-no-qualifying-type // stylelint-disable selector-no-qualifying-type
// //
// Textual form controls // Textual form controls
// //
.form-control { .form-control {
display: block; display: block;
width: 100%; width: 100%;
padding: $input-padding-y $input-padding-x; padding: $input-padding-y $input-padding-x;
font-size: $font-size-base; font-size: $font-size-base;
line-height: $input-line-height; line-height: $input-line-height;
color: $input-color; color: $input-color;
background-color: $input-bg; background-color: $input-bg;
background-clip: padding-box; background-clip: padding-box;
border: $input-border-width solid $input-border-color; border: $input-border-width solid $input-border-color;
// Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS. // Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS.
@if $enable-rounded { @if $enable-rounded {
// Manually use the if/else instead of the mixin to account for iOS override // Manually use the if/else instead of the mixin to account for iOS override
border-radius: $input-border-radius; border-radius: $input-border-radius;
} @else { } @else {
// Otherwise undo the iOS default // Otherwise undo the iOS default
border-radius: 0; border-radius: 0;
} }
@include box-shadow($input-box-shadow); @include box-shadow($input-box-shadow);
@include transition($input-transition); @include transition($input-transition);
// Unstyle the caret on `<select>`s in IE10+. // Unstyle the caret on `<select>`s in IE10+.
&::-ms-expand { &::-ms-expand {
background-color: transparent; background-color: transparent;
border: 0; border: 0;
} }
// Customize the `:focus` state to imitate native WebKit styles. // Customize the `:focus` state to imitate native WebKit styles.
@include form-control-focus(); @include form-control-focus();
// Placeholder // Placeholder
&::placeholder { &::placeholder {
color: $input-placeholder-color; color: $input-placeholder-color;
// Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526. // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.
opacity: 1; opacity: 1;
} }
// Disabled and read-only inputs // Disabled and read-only inputs
// //
// HTML5 says that controls under a fieldset > legend:first-child won't be // HTML5 says that controls under a fieldset > legend:first-child won't be
// disabled if the fieldset is disabled. Due to implementation difficulty, we // disabled if the fieldset is disabled. Due to implementation difficulty, we
// don't honor that edge case; we style them as disabled anyway. // don't honor that edge case; we style them as disabled anyway.
&:disabled, &:disabled,
&[readonly] { &[readonly] {
background-color: $input-disabled-bg; background-color: $input-disabled-bg;
// iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655. // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.
opacity: 1; opacity: 1;
} }
} }
select.form-control { select.form-control {
&:not([size]):not([multiple]) { &:not([size]):not([multiple]) {
height: $input-height; height: $input-height;
} }
&:focus::-ms-value { &:focus::-ms-value {
// Suppress the nested default white text on blue background highlight given to // Suppress the nested default white text on blue background highlight given to
// the selected option text when the (still closed) <select> receives focus // the selected option text when the (still closed) <select> receives focus
// in IE and (under certain conditions) Edge, as it looks bad and cannot be made to // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to
// match the appearance of the native widget. // match the appearance of the native widget.
// See https://github.com/twbs/bootstrap/issues/19398. // See https://github.com/twbs/bootstrap/issues/19398.
color: $input-color; color: $input-color;
background-color: $input-bg; background-color: $input-bg;
} }
} }
// Make file inputs better match text inputs by forcing them to new lines. // Make file inputs better match text inputs by forcing them to new lines.
.form-control-file, .form-control-file,
.form-control-range { .form-control-range {
display: block; display: block;
width: 100%; width: 100%;
} }
// //
// Labels // Labels
// //
// For use with horizontal and inline forms, when you need the label (or legend) // For use with horizontal and inline forms, when you need the label (or legend)
// text to align with the form controls. // text to align with the form controls.
.col-form-label { .col-form-label {
padding-top: calc(#{$input-padding-y} + #{$input-border-width}); padding-top: calc(#{$input-padding-y} + #{$input-border-width});
padding-bottom: calc(#{$input-padding-y} + #{$input-border-width}); padding-bottom: calc(#{$input-padding-y} + #{$input-border-width});
margin-bottom: 0; // Override the `<label>/<legend>` default margin-bottom: 0; // Override the `<label>/<legend>` default
font-size: inherit; // Override the `<legend>` default font-size: inherit; // Override the `<legend>` default
line-height: $input-line-height; line-height: $input-line-height;
} }
.col-form-label-lg { .col-form-label-lg {
padding-top: calc(#{$input-padding-y-lg} + #{$input-border-width}); padding-top: calc(#{$input-padding-y-lg} + #{$input-border-width});
padding-bottom: calc(#{$input-padding-y-lg} + #{$input-border-width}); padding-bottom: calc(#{$input-padding-y-lg} + #{$input-border-width});
font-size: $font-size-lg; font-size: $font-size-lg;
line-height: $input-line-height-lg; line-height: $input-line-height-lg;
} }
.col-form-label-sm { .col-form-label-sm {
padding-top: calc(#{$input-padding-y-sm} + #{$input-border-width}); padding-top: calc(#{$input-padding-y-sm} + #{$input-border-width});
padding-bottom: calc(#{$input-padding-y-sm} + #{$input-border-width}); padding-bottom: calc(#{$input-padding-y-sm} + #{$input-border-width});
font-size: $font-size-sm; font-size: $font-size-sm;
line-height: $input-line-height-sm; line-height: $input-line-height-sm;
} }
// Readonly controls as plain text // Readonly controls as plain text
// //
// Apply class to a readonly input to make it appear like regular plain // Apply class to a readonly input to make it appear like regular plain
// text (without any border, background color, focus indicator) // text (without any border, background color, focus indicator)
.form-control-plaintext { .form-control-plaintext {
display: block; display: block;
width: 100%; width: 100%;
padding-top: $input-padding-y; padding-top: $input-padding-y;
padding-bottom: $input-padding-y; padding-bottom: $input-padding-y;
margin-bottom: 0; // match inputs if this class comes on inputs with default margins margin-bottom: 0; // match inputs if this class comes on inputs with default margins
line-height: $input-line-height; line-height: $input-line-height;
color: $input-plaintext-color; color: $input-plaintext-color;
background-color: transparent; background-color: transparent;
border: solid transparent; border: solid transparent;
border-width: $input-border-width 0; border-width: $input-border-width 0;
&.form-control-sm, &.form-control-sm,
&.form-control-lg { &.form-control-lg {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
} }
} }
// Form control sizing // Form control sizing
// //
// Build on `.form-control` with modifier classes to decrease or increase the // Build on `.form-control` with modifier classes to decrease or increase the
// height and font-size of form controls. // height and font-size of form controls.
// //
// The `.form-group-* form-control` variations are sadly duplicated to avoid the // The `.form-group-* form-control` variations are sadly duplicated to avoid the
// issue documented in https://github.com/twbs/bootstrap/issues/15074. // issue documented in https://github.com/twbs/bootstrap/issues/15074.
.form-control-sm { .form-control-sm {
padding: $input-padding-y-sm $input-padding-x-sm; padding: $input-padding-y-sm $input-padding-x-sm;
font-size: $font-size-sm; font-size: $font-size-sm;
line-height: $input-line-height-sm; line-height: $input-line-height-sm;
@include border-radius($input-border-radius-sm); @include border-radius($input-border-radius-sm);
} }
select.form-control-sm { select.form-control-sm {
&:not([size]):not([multiple]) { &:not([size]):not([multiple]) {
height: $input-height-sm; height: $input-height-sm;
} }
} }
.form-control-lg { .form-control-lg {
padding: $input-padding-y-lg $input-padding-x-lg; padding: $input-padding-y-lg $input-padding-x-lg;
font-size: $font-size-lg; font-size: $font-size-lg;
line-height: $input-line-height-lg; line-height: $input-line-height-lg;
@include border-radius($input-border-radius-lg); @include border-radius($input-border-radius-lg);
} }
select.form-control-lg { select.form-control-lg {
&:not([size]):not([multiple]) { &:not([size]):not([multiple]) {
height: $input-height-lg; height: $input-height-lg;
} }
} }
// Form groups // Form groups
// //
// Designed to help with the organization and spacing of vertical forms. For // Designed to help with the organization and spacing of vertical forms. For
// horizontal forms, use the predefined grid classes. // horizontal forms, use the predefined grid classes.
.form-group { .form-group {
margin-bottom: $form-group-margin-bottom; margin-bottom: $form-group-margin-bottom;
} }
.form-text { .form-text {
display: block; display: block;
margin-top: $form-text-margin-top; margin-top: $form-text-margin-top;
} }
// Form grid // Form grid
// //
// Special replacement for our grid system's `.row` for tighter form layouts. // Special replacement for our grid system's `.row` for tighter form layouts.
.form-row { .form-row {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin-right: -5px; margin-right: -5px;
margin-left: -5px; margin-left: -5px;
> .col, > .col,
> [class*="col-"] { > [class*="col-"] {
padding-right: 5px; padding-right: 5px;
padding-left: 5px; padding-left: 5px;
} }
} }
// Checkboxes and radios // Checkboxes and radios
// //
// Indent the labels to position radios/checkboxes as hanging controls. // Indent the labels to position radios/checkboxes as hanging controls.
.form-check { .form-check {
position: relative; position: relative;
display: block; display: block;
padding-left: $form-check-input-gutter; padding-left: $form-check-input-gutter;
} }
.form-check-input { .form-check-input {
position: absolute; position: absolute;
margin-top: $form-check-input-margin-y; margin-top: $form-check-input-margin-y;
margin-left: -$form-check-input-gutter; margin-left: -$form-check-input-gutter;
&:disabled ~ .form-check-label { &:disabled ~ .form-check-label {
color: $text-muted; color: $text-muted;
} }
} }
.form-check-label { .form-check-label {
margin-bottom: 0; // Override default `<label>` bottom margin margin-bottom: 0; // Override default `<label>` bottom margin
} }
.form-check-inline { .form-check-inline {
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
padding-left: 0; // Override base .form-check padding-left: 0; // Override base .form-check
margin-right: $form-check-inline-margin-x; margin-right: $form-check-inline-margin-x;
// Undo .form-check-input defaults and add some `margin-right`. // Undo .form-check-input defaults and add some `margin-right`.
.form-check-input { .form-check-input {
position: static; position: static;
margin-top: 0; margin-top: 0;
margin-right: $form-check-inline-input-margin-x; margin-right: $form-check-inline-input-margin-x;
margin-left: 0; margin-left: 0;
} }
} }
// Form validation // Form validation
// //
// Provide feedback to users when form field values are valid or invalid. Works // Provide feedback to users when form field values are valid or invalid. Works
// primarily for client-side validation via scoped `:invalid` and `:valid` // primarily for client-side validation via scoped `:invalid` and `:valid`
// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for // pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for
// server side validation. // server side validation.
@include form-validation-state("valid", $form-feedback-valid-color); @include form-validation-state("valid", $form-feedback-valid-color);
@include form-validation-state("invalid", $form-feedback-invalid-color); @include form-validation-state("invalid", $form-feedback-invalid-color);
// Inline forms // Inline forms
// //
// Make forms appear inline(-block) by adding the `.form-inline` class. Inline // Make forms appear inline(-block) by adding the `.form-inline` class. Inline
// forms begin stacked on extra small (mobile) devices and then go inline when // forms begin stacked on extra small (mobile) devices and then go inline when
// viewports reach <768px. // viewports reach <768px.
// //
// Requires wrapping inputs and labels with `.form-group` for proper display of // Requires wrapping inputs and labels with `.form-group` for proper display of
// default HTML form controls and our custom form controls (e.g., input groups). // default HTML form controls and our custom form controls (e.g., input groups).
.form-inline { .form-inline {
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;
align-items: center; // Prevent shorter elements from growing to same height as others (e.g., small buttons growing to normal sized button height) align-items: center; // Prevent shorter elements from growing to same height as others (e.g., small buttons growing to normal sized button height)
// Because we use flex, the initial sizing of checkboxes is collapsed and // Because we use flex, the initial sizing of checkboxes is collapsed and
// doesn't occupy the full-width (which is what we want for xs grid tier), // doesn't occupy the full-width (which is what we want for xs grid tier),
// so we force that here. // so we force that here.
.form-check { .form-check {
width: 100%; width: 100%;
} }
// Kick in the inline // Kick in the inline
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
label { label {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
margin-bottom: 0; margin-bottom: 0;
} }
// Inline-block all the things for "inline" // Inline-block all the things for "inline"
.form-group { .form-group {
display: flex; display: flex;
flex: 0 0 auto; flex: 0 0 auto;
flex-flow: row wrap; flex-flow: row wrap;
align-items: center; align-items: center;
margin-bottom: 0; margin-bottom: 0;
} }
// Allow folks to *not* use `.form-group` // Allow folks to *not* use `.form-group`
.form-control { .form-control {
display: inline-block; display: inline-block;
width: auto; // Prevent labels from stacking above inputs in `.form-group` width: auto; // Prevent labels from stacking above inputs in `.form-group`
vertical-align: middle; vertical-align: middle;
} }
// Make static controls behave like regular ones // Make static controls behave like regular ones
.form-control-plaintext { .form-control-plaintext {
display: inline-block; display: inline-block;
} }
.input-group, .input-group,
.custom-select { .custom-select {
width: auto; width: auto;
} }
// Remove default margin on radios/checkboxes that were used for stacking, and // Remove default margin on radios/checkboxes that were used for stacking, and
// then undo the floating of radios and checkboxes to match. // then undo the floating of radios and checkboxes to match.
.form-check { .form-check {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: auto; width: auto;
padding-left: 0; padding-left: 0;
} }
.form-check-input { .form-check-input {
position: relative; position: relative;
margin-top: 0; margin-top: 0;
margin-right: $form-check-input-margin-x; margin-right: $form-check-input-margin-x;
margin-left: 0; margin-left: 0;
} }
.custom-control { .custom-control {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.custom-control-label { .custom-control-label {
margin-bottom: 0; margin-bottom: 0;
} }
} }
} }

View File

@@ -1,86 +1,86 @@
// Bootstrap functions // Bootstrap functions
// //
// Utility mixins and functions for evalutating source code across our variables, maps, and mixins. // Utility mixins and functions for evalutating source code across our variables, maps, and mixins.
// Ascending // Ascending
// Used to evaluate Sass maps like our grid breakpoints. // Used to evaluate Sass maps like our grid breakpoints.
@mixin _assert-ascending($map, $map-name) { @mixin _assert-ascending($map, $map-name) {
$prev-key: null; $prev-key: null;
$prev-num: null; $prev-num: null;
@each $key, $num in $map { @each $key, $num in $map {
@if $prev-num == null { @if $prev-num == null {
// Do nothing // Do nothing
} @else if not comparable($prev-num, $num) { } @else if not comparable($prev-num, $num) {
@warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !"; @warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !";
} @else if $prev-num >= $num { } @else if $prev-num >= $num {
@warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !"; @warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !";
} }
$prev-key: $key; $prev-key: $key;
$prev-num: $num; $prev-num: $num;
} }
} }
// Starts at zero // Starts at zero
// Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0. // Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0.
@mixin _assert-starts-at-zero($map) { @mixin _assert-starts-at-zero($map) {
$values: map-values($map); $values: map-values($map);
$first-value: nth($values, 1); $first-value: nth($values, 1);
@if $first-value != 0 { @if $first-value != 0 {
@warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}."; @warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}.";
} }
} }
// Replace `$search` with `$replace` in `$string` // Replace `$search` with `$replace` in `$string`
// Used on our SVG icon backgrounds for custom forms. // Used on our SVG icon backgrounds for custom forms.
// //
// @author Hugo Giraudel // @author Hugo Giraudel
// @param {String} $string - Initial string // @param {String} $string - Initial string
// @param {String} $search - Substring to replace // @param {String} $search - Substring to replace
// @param {String} $replace ('') - New value // @param {String} $replace ('') - New value
// @return {String} - Updated string // @return {String} - Updated string
@function str-replace($string, $search, $replace: "") { @function str-replace($string, $search, $replace: "") {
$index: str-index($string, $search); $index: str-index($string, $search);
@if $index { @if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace); @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
} }
@return $string; @return $string;
} }
// Color contrast // Color contrast
@function color-yiq($color) { @function color-yiq($color) {
$r: red($color); $r: red($color);
$g: green($color); $g: green($color);
$b: blue($color); $b: blue($color);
$yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000; $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
@if ($yiq >= $yiq-contrasted-threshold) { @if ($yiq >= $yiq-contrasted-threshold) {
@return $yiq-text-dark; @return $yiq-text-dark;
} @else { } @else {
@return $yiq-text-light; @return $yiq-text-light;
} }
} }
// Retrieve color Sass maps // Retrieve color Sass maps
@function color($key: "blue") { @function color($key: "blue") {
@return map-get($colors, $key); @return map-get($colors, $key);
} }
@function theme-color($key: "primary") { @function theme-color($key: "primary") {
@return map-get($theme-colors, $key); @return map-get($theme-colors, $key);
} }
@function gray($key: "100") { @function gray($key: "100") {
@return map-get($grays, $key); @return map-get($grays, $key);
} }
// Request a theme color level // Request a theme color level
@function theme-color-level($color-name: "primary", $level: 0) { @function theme-color-level($color-name: "primary", $level: 0) {
$color: theme-color($color-name); $color: theme-color($color-name);
$color-base: if($level > 0, $black, $white); $color-base: if($level > 0, $black, $white);
$level: abs($level); $level: abs($level);
@return mix($color-base, $color, $level * $theme-color-interval); @return mix($color-base, $color, $level * $theme-color-interval);
} }

View File

@@ -1,52 +1,52 @@
// Container widths // Container widths
// //
// Set the container width, and override it for fixed navbars in media queries. // Set the container width, and override it for fixed navbars in media queries.
@if $enable-grid-classes { @if $enable-grid-classes {
.container { .container {
@include make-container(); @include make-container();
@include make-container-max-widths(); @include make-container-max-widths();
} }
} }
// Fluid container // Fluid container
// //
// Utilizes the mixin meant for fixed width containers, but with 100% width for // Utilizes the mixin meant for fixed width containers, but with 100% width for
// fluid, full width layouts. // fluid, full width layouts.
@if $enable-grid-classes { @if $enable-grid-classes {
.container-fluid { .container-fluid {
@include make-container(); @include make-container();
} }
} }
// Row // Row
// //
// Rows contain and clear the floats of your columns. // Rows contain and clear the floats of your columns.
@if $enable-grid-classes { @if $enable-grid-classes {
.row { .row {
@include make-row(); @include make-row();
} }
// Remove the negative margin from default .row, then the horizontal padding // Remove the negative margin from default .row, then the horizontal padding
// from all immediate children columns (to prevent runaway style inheritance). // from all immediate children columns (to prevent runaway style inheritance).
.no-gutters { .no-gutters {
margin-right: 0; margin-right: 0;
margin-left: 0; margin-left: 0;
> .col, > .col,
> [class*="col-"] { > [class*="col-"] {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
} }
} }
} }
// Columns // Columns
// //
// Common styles for small and large grid columns // Common styles for small and large grid columns
@if $enable-grid-classes { @if $enable-grid-classes {
@include make-grid-columns(); @include make-grid-columns();
} }

View File

@@ -1,42 +1,42 @@
// Responsive images (ensure images don't scale beyond their parents) // Responsive images (ensure images don't scale beyond their parents)
// //
// This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s. // This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s.
// We previously tried the "images are responsive by default" approach in Bootstrap v2, // We previously tried the "images are responsive by default" approach in Bootstrap v2,
// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps) // and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)
// which weren't expecting the images within themselves to be involuntarily resized. // which weren't expecting the images within themselves to be involuntarily resized.
// See also https://github.com/twbs/bootstrap/issues/18178 // See also https://github.com/twbs/bootstrap/issues/18178
.img-fluid { .img-fluid {
@include img-fluid; @include img-fluid;
} }
// Image thumbnails // Image thumbnails
.img-thumbnail { .img-thumbnail {
padding: $thumbnail-padding; padding: $thumbnail-padding;
background-color: $thumbnail-bg; background-color: $thumbnail-bg;
border: $thumbnail-border-width solid $thumbnail-border-color; border: $thumbnail-border-width solid $thumbnail-border-color;
@include border-radius($thumbnail-border-radius); @include border-radius($thumbnail-border-radius);
@include box-shadow($thumbnail-box-shadow); @include box-shadow($thumbnail-box-shadow);
// Keep them at most 100% wide // Keep them at most 100% wide
@include img-fluid; @include img-fluid;
} }
// //
// Figures // Figures
// //
.figure { .figure {
// Ensures the caption's text aligns with the image. // Ensures the caption's text aligns with the image.
display: inline-block; display: inline-block;
} }
.figure-img { .figure-img {
margin-bottom: ($spacer / 2); margin-bottom: ($spacer / 2);
line-height: 1; line-height: 1;
} }
.figure-caption { .figure-caption {
font-size: $figure-caption-font-size; font-size: $figure-caption-font-size;
color: $figure-caption-color; color: $figure-caption-color;
} }

View File

@@ -1,16 +1,16 @@
.jumbotron { .jumbotron {
padding: $jumbotron-padding ($jumbotron-padding / 2); padding: $jumbotron-padding ($jumbotron-padding / 2);
margin-bottom: $jumbotron-padding; margin-bottom: $jumbotron-padding;
background-color: $jumbotron-bg; background-color: $jumbotron-bg;
@include border-radius($border-radius-lg); @include border-radius($border-radius-lg);
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
padding: ($jumbotron-padding * 2) $jumbotron-padding; padding: ($jumbotron-padding * 2) $jumbotron-padding;
} }
} }
.jumbotron-fluid { .jumbotron-fluid {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
@include border-radius(0); @include border-radius(0);
} }

View File

@@ -1,115 +1,115 @@
// Base class // Base class
// //
// Easily usable on <ul>, <ol>, or <div>. // Easily usable on <ul>, <ol>, or <div>.
.list-group { .list-group {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
// No need to set list-style: none; since .list-group-item is block level // No need to set list-style: none; since .list-group-item is block level
padding-left: 0; // reset padding because ul and ol padding-left: 0; // reset padding because ul and ol
margin-bottom: 0; margin-bottom: 0;
} }
// Interactive list items // Interactive list items
// //
// Use anchor or button elements instead of `li`s or `div`s to create interactive // Use anchor or button elements instead of `li`s or `div`s to create interactive
// list items. Includes an extra `.active` modifier class for selected items. // list items. Includes an extra `.active` modifier class for selected items.
.list-group-item-action { .list-group-item-action {
width: 100%; // For `<button>`s (anchors become 100% by default though) width: 100%; // For `<button>`s (anchors become 100% by default though)
color: $list-group-action-color; color: $list-group-action-color;
text-align: inherit; // For `<button>`s (anchors inherit) text-align: inherit; // For `<button>`s (anchors inherit)
// Hover state // Hover state
@include hover-focus { @include hover-focus {
color: $list-group-action-hover-color; color: $list-group-action-hover-color;
text-decoration: none; text-decoration: none;
background-color: $list-group-hover-bg; background-color: $list-group-hover-bg;
} }
&:active { &:active {
color: $list-group-action-active-color; color: $list-group-action-active-color;
background-color: $list-group-action-active-bg; background-color: $list-group-action-active-bg;
} }
} }
// Individual list items // Individual list items
// //
// Use on `li`s or `div`s within the `.list-group` parent. // Use on `li`s or `div`s within the `.list-group` parent.
.list-group-item { .list-group-item {
position: relative; position: relative;
display: block; display: block;
padding: $list-group-item-padding-y $list-group-item-padding-x; padding: $list-group-item-padding-y $list-group-item-padding-x;
// Place the border on the list items and negative margin up for better styling // Place the border on the list items and negative margin up for better styling
margin-bottom: -$list-group-border-width; margin-bottom: -$list-group-border-width;
background-color: $list-group-bg; background-color: $list-group-bg;
border: $list-group-border-width solid $list-group-border-color; border: $list-group-border-width solid $list-group-border-color;
&:first-child { &:first-child {
@include border-top-radius($list-group-border-radius); @include border-top-radius($list-group-border-radius);
} }
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
@include border-bottom-radius($list-group-border-radius); @include border-bottom-radius($list-group-border-radius);
} }
@include hover-focus { @include hover-focus {
z-index: 1; // Place hover/active items above their siblings for proper border styling z-index: 1; // Place hover/active items above their siblings for proper border styling
text-decoration: none; text-decoration: none;
} }
&.disabled, &.disabled,
&:disabled { &:disabled {
color: $list-group-disabled-color; color: $list-group-disabled-color;
background-color: $list-group-disabled-bg; background-color: $list-group-disabled-bg;
} }
// Include both here for `<a>`s and `<button>`s // Include both here for `<a>`s and `<button>`s
&.active { &.active {
z-index: 2; // Place active items above their siblings for proper border styling z-index: 2; // Place active items above their siblings for proper border styling
color: $list-group-active-color; color: $list-group-active-color;
background-color: $list-group-active-bg; background-color: $list-group-active-bg;
border-color: $list-group-active-border-color; border-color: $list-group-active-border-color;
} }
} }
// Flush list items // Flush list items
// //
// Remove borders and border-radius to keep list group items edge-to-edge. Most // Remove borders and border-radius to keep list group items edge-to-edge. Most
// useful within other components (e.g., cards). // useful within other components (e.g., cards).
.list-group-flush { .list-group-flush {
.list-group-item { .list-group-item {
border-right: 0; border-right: 0;
border-left: 0; border-left: 0;
@include border-radius(0); @include border-radius(0);
} }
&:first-child { &:first-child {
.list-group-item:first-child { .list-group-item:first-child {
border-top: 0; border-top: 0;
} }
} }
&:last-child { &:last-child {
.list-group-item:last-child { .list-group-item:last-child {
border-bottom: 0; border-bottom: 0;
} }
} }
} }
// Contextual variants // Contextual variants
// //
// Add modifier classes to change text and background color on individual items. // Add modifier classes to change text and background color on individual items.
// Organizationally, this must come after the `:hover` states. // Organizationally, this must come after the `:hover` states.
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
@include list-group-item-variant($color, theme-color-level($color, -9), theme-color-level($color, 6)); @include list-group-item-variant($color, theme-color-level($color, -9), theme-color-level($color, 6));
} }

View File

@@ -1,8 +1,8 @@
.media { .media {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
} }
.media-body { .media-body {
flex: 1; flex: 1;
} }

View File

@@ -1,41 +1,41 @@
// Toggles // Toggles
// //
// Used in conjunction with global variables to enable certain theme features. // Used in conjunction with global variables to enable certain theme features.
// Utilities // Utilities
@import "mixins/breakpoints"; @import "mixins/breakpoints";
@import "mixins/hover"; @import "mixins/hover";
@import "mixins/image"; @import "mixins/image";
@import "mixins/badge"; @import "mixins/badge";
@import "mixins/resize"; @import "mixins/resize";
@import "mixins/screen-reader"; @import "mixins/screen-reader";
@import "mixins/size"; @import "mixins/size";
@import "mixins/reset-text"; @import "mixins/reset-text";
@import "mixins/text-emphasis"; @import "mixins/text-emphasis";
@import "mixins/text-hide"; @import "mixins/text-hide";
@import "mixins/text-truncate"; @import "mixins/text-truncate";
@import "mixins/visibility"; @import "mixins/visibility";
// // Components // // Components
@import "mixins/alert"; @import "mixins/alert";
@import "mixins/buttons"; @import "mixins/buttons";
@import "mixins/caret"; @import "mixins/caret";
@import "mixins/pagination"; @import "mixins/pagination";
@import "mixins/lists"; @import "mixins/lists";
@import "mixins/list-group"; @import "mixins/list-group";
@import "mixins/nav-divider"; @import "mixins/nav-divider";
@import "mixins/forms"; @import "mixins/forms";
@import "mixins/table-row"; @import "mixins/table-row";
// // Skins // // Skins
@import "mixins/background-variant"; @import "mixins/background-variant";
@import "mixins/border-radius"; @import "mixins/border-radius";
@import "mixins/box-shadow"; @import "mixins/box-shadow";
@import "mixins/gradients"; @import "mixins/gradients";
@import "mixins/transition"; @import "mixins/transition";
// // Layout // // Layout
@import "mixins/clearfix"; @import "mixins/clearfix";
@import "mixins/grid-framework"; @import "mixins/grid-framework";
@import "mixins/grid"; @import "mixins/grid";
@import "mixins/float"; @import "mixins/float";

View File

@@ -1,168 +1,168 @@
// .modal-open - body class for killing the scroll // .modal-open - body class for killing the scroll
// .modal - container to scroll within // .modal - container to scroll within
// .modal-dialog - positioning shell for the actual modal // .modal-dialog - positioning shell for the actual modal
// .modal-content - actual modal w/ bg and corners and stuff // .modal-content - actual modal w/ bg and corners and stuff
// Kill the scroll on the body // Kill the scroll on the body
.modal-open { .modal-open {
overflow: hidden; overflow: hidden;
} }
// Container that the modal scrolls within // Container that the modal scrolls within
.modal { .modal {
position: fixed; position: fixed;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: $zindex-modal; z-index: $zindex-modal;
display: none; display: none;
overflow: hidden; overflow: hidden;
// Prevent Chrome on Windows from adding a focus outline. For details, see // Prevent Chrome on Windows from adding a focus outline. For details, see
// https://github.com/twbs/bootstrap/pull/10951. // https://github.com/twbs/bootstrap/pull/10951.
outline: 0; outline: 0;
// We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a // We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a
// gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342 // gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342
// See also https://github.com/twbs/bootstrap/issues/17695 // See also https://github.com/twbs/bootstrap/issues/17695
.modal-open & { .modal-open & {
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
} }
} }
// Shell div to position the modal with bottom padding // Shell div to position the modal with bottom padding
.modal-dialog { .modal-dialog {
position: relative; position: relative;
width: auto; width: auto;
margin: $modal-dialog-margin; margin: $modal-dialog-margin;
// allow clicks to pass through for custom click handling to close modal // allow clicks to pass through for custom click handling to close modal
pointer-events: none; pointer-events: none;
// When fading in the modal, animate it to slide down // When fading in the modal, animate it to slide down
.modal.fade & { .modal.fade & {
@include transition($modal-transition); @include transition($modal-transition);
transform: translate(0, -25%); transform: translate(0, -25%);
} }
.modal.show & { .modal.show & {
transform: translate(0, 0); transform: translate(0, 0);
} }
} }
.modal-dialog-centered { .modal-dialog-centered {
display: flex; display: flex;
align-items: center; align-items: center;
min-height: calc(100% - (#{$modal-dialog-margin} * 2)); min-height: calc(100% - (#{$modal-dialog-margin} * 2));
} }
// Actual modal // Actual modal
.modal-content { .modal-content {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog` width: 100%; // Ensure `.modal-content` extends the full width of the parent `.modal-dialog`
// counteract the pointer-events: none; in the .modal-dialog // counteract the pointer-events: none; in the .modal-dialog
pointer-events: auto; pointer-events: auto;
background-color: $modal-content-bg; background-color: $modal-content-bg;
background-clip: padding-box; background-clip: padding-box;
border: $modal-content-border-width solid $modal-content-border-color; border: $modal-content-border-width solid $modal-content-border-color;
@include border-radius($modal-content-border-radius); @include border-radius($modal-content-border-radius);
@include box-shadow($modal-content-box-shadow-xs); @include box-shadow($modal-content-box-shadow-xs);
// Remove focus outline from opened modal // Remove focus outline from opened modal
outline: 0; outline: 0;
} }
// Modal background // Modal background
.modal-backdrop { .modal-backdrop {
position: fixed; position: fixed;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: $zindex-modal-backdrop; z-index: $zindex-modal-backdrop;
background-color: $modal-backdrop-bg; background-color: $modal-backdrop-bg;
// Fade for backdrop // Fade for backdrop
&.fade { opacity: 0; } &.fade { opacity: 0; }
&.show { opacity: $modal-backdrop-opacity; } &.show { opacity: $modal-backdrop-opacity; }
} }
// Modal header // Modal header
// Top section of the modal w/ title and dismiss // Top section of the modal w/ title and dismiss
.modal-header { .modal-header {
display: flex; display: flex;
align-items: flex-start; // so the close btn always stays on the upper right corner align-items: flex-start; // so the close btn always stays on the upper right corner
justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends justify-content: space-between; // Put modal header elements (title and dismiss) on opposite ends
padding: $modal-header-padding; padding: $modal-header-padding;
border-bottom: $modal-header-border-width solid $modal-header-border-color; border-bottom: $modal-header-border-width solid $modal-header-border-color;
@include border-top-radius($modal-content-border-radius); @include border-top-radius($modal-content-border-radius);
.close { .close {
padding: $modal-header-padding; padding: $modal-header-padding;
// auto on the left force icon to the right even when there is no .modal-title // auto on the left force icon to the right even when there is no .modal-title
margin: (-$modal-header-padding) (-$modal-header-padding) (-$modal-header-padding) auto; margin: (-$modal-header-padding) (-$modal-header-padding) (-$modal-header-padding) auto;
} }
} }
// Title text within header // Title text within header
.modal-title { .modal-title {
margin-bottom: 0; margin-bottom: 0;
line-height: $modal-title-line-height; line-height: $modal-title-line-height;
} }
// Modal body // Modal body
// Where all modal content resides (sibling of .modal-header and .modal-footer) // Where all modal content resides (sibling of .modal-header and .modal-footer)
.modal-body { .modal-body {
position: relative; position: relative;
// Enable `flex-grow: 1` so that the body take up as much space as possible // Enable `flex-grow: 1` so that the body take up as much space as possible
// when should there be a fixed height on `.modal-dialog`. // when should there be a fixed height on `.modal-dialog`.
flex: 1 1 auto; flex: 1 1 auto;
padding: $modal-inner-padding; padding: $modal-inner-padding;
} }
// Footer (for actions) // Footer (for actions)
.modal-footer { .modal-footer {
display: flex; display: flex;
align-items: center; // vertically center align-items: center; // vertically center
justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items justify-content: flex-end; // Right align buttons with flex property because text-align doesn't work on flex items
padding: $modal-inner-padding; padding: $modal-inner-padding;
border-top: $modal-footer-border-width solid $modal-footer-border-color; border-top: $modal-footer-border-width solid $modal-footer-border-color;
// Easily place margin between footer elements // Easily place margin between footer elements
> :not(:first-child) { margin-left: .25rem; } > :not(:first-child) { margin-left: .25rem; }
> :not(:last-child) { margin-right: .25rem; } > :not(:last-child) { margin-right: .25rem; }
} }
// Measure scrollbar width for padding body during modal show/hide // Measure scrollbar width for padding body during modal show/hide
.modal-scrollbar-measure { .modal-scrollbar-measure {
position: absolute; position: absolute;
top: -9999px; top: -9999px;
width: 50px; width: 50px;
height: 50px; height: 50px;
overflow: scroll; overflow: scroll;
} }
// Scale up the modal // Scale up the modal
@include media-breakpoint-up(sm) { @include media-breakpoint-up(sm) {
// Automatically set modal's width for larger viewports // Automatically set modal's width for larger viewports
.modal-dialog { .modal-dialog {
max-width: $modal-md; max-width: $modal-md;
margin: $modal-dialog-margin-y-sm-up auto; margin: $modal-dialog-margin-y-sm-up auto;
} }
.modal-dialog-centered { .modal-dialog-centered {
min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2)); min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2));
} }
.modal-content { .modal-content {
@include box-shadow($modal-content-box-shadow-sm-up); @include box-shadow($modal-content-box-shadow-sm-up);
} }
.modal-sm { max-width: $modal-sm; } .modal-sm { max-width: $modal-sm; }
} }
@include media-breakpoint-up(lg) { @include media-breakpoint-up(lg) {
.modal-lg { max-width: $modal-lg; } .modal-lg { max-width: $modal-lg; }
} }

View File

@@ -1,118 +1,118 @@
// Base class // Base class
// //
// Kickstart any navigation component with a set of style resets. Works with // Kickstart any navigation component with a set of style resets. Works with
// `<nav>`s or `<ul>`s. // `<nav>`s or `<ul>`s.
.nav { .nav {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding-left: 0; padding-left: 0;
margin-bottom: 0; margin-bottom: 0;
list-style: none; list-style: none;
} }
.nav-link { .nav-link {
display: block; display: block;
padding: $nav-link-padding-y $nav-link-padding-x; padding: $nav-link-padding-y $nav-link-padding-x;
@include hover-focus { @include hover-focus {
text-decoration: none; text-decoration: none;
} }
// Disabled state lightens text // Disabled state lightens text
&.disabled { &.disabled {
color: $nav-link-disabled-color; color: $nav-link-disabled-color;
} }
} }
// //
// Tabs // Tabs
// //
.nav-tabs { .nav-tabs {
border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color; border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color;
.nav-item { .nav-item {
margin-bottom: -$nav-tabs-border-width; margin-bottom: -$nav-tabs-border-width;
} }
.nav-link { .nav-link {
border: $nav-tabs-border-width solid transparent; border: $nav-tabs-border-width solid transparent;
@include border-top-radius($nav-tabs-border-radius); @include border-top-radius($nav-tabs-border-radius);
@include hover-focus { @include hover-focus {
border-color: $nav-tabs-link-hover-border-color; border-color: $nav-tabs-link-hover-border-color;
} }
&.disabled { &.disabled {
color: $nav-link-disabled-color; color: $nav-link-disabled-color;
background-color: transparent; background-color: transparent;
border-color: transparent; border-color: transparent;
} }
} }
.nav-link.active, .nav-link.active,
.nav-item.show .nav-link { .nav-item.show .nav-link {
color: $nav-tabs-link-active-color; color: $nav-tabs-link-active-color;
background-color: $nav-tabs-link-active-bg; background-color: $nav-tabs-link-active-bg;
border-color: $nav-tabs-link-active-border-color; border-color: $nav-tabs-link-active-border-color;
} }
.dropdown-menu { .dropdown-menu {
// Make dropdown border overlap tab border // Make dropdown border overlap tab border
margin-top: -$nav-tabs-border-width; margin-top: -$nav-tabs-border-width;
// Remove the top rounded corners here since there is a hard edge above the menu // Remove the top rounded corners here since there is a hard edge above the menu
@include border-top-radius(0); @include border-top-radius(0);
} }
} }
// //
// Pills // Pills
// //
.nav-pills { .nav-pills {
.nav-link { .nav-link {
@include border-radius($nav-pills-border-radius); @include border-radius($nav-pills-border-radius);
} }
.nav-link.active, .nav-link.active,
.show > .nav-link { .show > .nav-link {
color: $nav-pills-link-active-color; color: $nav-pills-link-active-color;
background-color: $nav-pills-link-active-bg; background-color: $nav-pills-link-active-bg;
} }
} }
// //
// Justified variants // Justified variants
// //
.nav-fill { .nav-fill {
.nav-item { .nav-item {
flex: 1 1 auto; flex: 1 1 auto;
text-align: center; text-align: center;
} }
} }
.nav-justified { .nav-justified {
.nav-item { .nav-item {
flex-basis: 0; flex-basis: 0;
flex-grow: 1; flex-grow: 1;
text-align: center; text-align: center;
} }
} }
// Tabbable tabs // Tabbable tabs
// //
// Hide tabbable panes to start, show them when `.active` // Hide tabbable panes to start, show them when `.active`
.tab-content { .tab-content {
> .tab-pane { > .tab-pane {
display: none; display: none;
} }
> .active { > .active {
display: block; display: block;
} }
} }

View File

@@ -1,299 +1,299 @@
// Contents // Contents
// //
// Navbar // Navbar
// Navbar brand // Navbar brand
// Navbar nav // Navbar nav
// Navbar text // Navbar text
// Navbar divider // Navbar divider
// Responsive navbar // Responsive navbar
// Navbar position // Navbar position
// Navbar themes // Navbar themes
// Navbar // Navbar
// //
// Provide a static navbar from which we expand to create full-width, fixed, and // Provide a static navbar from which we expand to create full-width, fixed, and
// other navbar variations. // other navbar variations.
.navbar { .navbar {
position: relative; position: relative;
display: flex; display: flex;
flex-wrap: wrap; // allow us to do the line break for collapsing content flex-wrap: wrap; // allow us to do the line break for collapsing content
align-items: center; align-items: center;
justify-content: space-between; // space out brand from logo justify-content: space-between; // space out brand from logo
padding: $navbar-padding-y $navbar-padding-x; padding: $navbar-padding-y $navbar-padding-x;
// Because flex properties aren't inherited, we need to redeclare these first // Because flex properties aren't inherited, we need to redeclare these first
// few properities so that content nested within behave properly. // few properities so that content nested within behave properly.
> .container, > .container,
> .container-fluid { > .container-fluid {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
} }
} }
// Navbar brand // Navbar brand
// //
// Used for brand, project, or site names. // Used for brand, project, or site names.
.navbar-brand { .navbar-brand {
display: inline-block; display: inline-block;
padding-top: $navbar-brand-padding-y; padding-top: $navbar-brand-padding-y;
padding-bottom: $navbar-brand-padding-y; padding-bottom: $navbar-brand-padding-y;
margin-right: $navbar-padding-x; margin-right: $navbar-padding-x;
font-size: $navbar-brand-font-size; font-size: $navbar-brand-font-size;
line-height: inherit; line-height: inherit;
white-space: nowrap; white-space: nowrap;
@include hover-focus { @include hover-focus {
text-decoration: none; text-decoration: none;
} }
} }
// Navbar nav // Navbar nav
// //
// Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`). // Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).
.navbar-nav { .navbar-nav {
display: flex; display: flex;
flex-direction: column; // cannot use `inherit` to get the `.navbar`s value flex-direction: column; // cannot use `inherit` to get the `.navbar`s value
padding-left: 0; padding-left: 0;
margin-bottom: 0; margin-bottom: 0;
list-style: none; list-style: none;
.nav-link { .nav-link {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
} }
.dropdown-menu { .dropdown-menu {
position: static; position: static;
float: none; float: none;
} }
} }
// Navbar text // Navbar text
// //
// //
.navbar-text { .navbar-text {
display: inline-block; display: inline-block;
padding-top: $nav-link-padding-y; padding-top: $nav-link-padding-y;
padding-bottom: $nav-link-padding-y; padding-bottom: $nav-link-padding-y;
} }
// Responsive navbar // Responsive navbar
// //
// Custom styles for responsive collapsing and toggling of navbar contents. // Custom styles for responsive collapsing and toggling of navbar contents.
// Powered by the collapse Bootstrap JavaScript plugin. // Powered by the collapse Bootstrap JavaScript plugin.
// When collapsed, prevent the toggleable navbar contents from appearing in // When collapsed, prevent the toggleable navbar contents from appearing in
// the default flexbox row orienation. Requires the use of `flex-wrap: wrap` // the default flexbox row orienation. Requires the use of `flex-wrap: wrap`
// on the `.navbar` parent. // on the `.navbar` parent.
.navbar-collapse { .navbar-collapse {
flex-basis: 100%; flex-basis: 100%;
flex-grow: 1; flex-grow: 1;
// For always expanded or extra full navbars, ensure content aligns itself // For always expanded or extra full navbars, ensure content aligns itself
// properly vertically. Can be easily overridden with flex utilities. // properly vertically. Can be easily overridden with flex utilities.
align-items: center; align-items: center;
} }
// Button for toggling the navbar when in its collapsed state // Button for toggling the navbar when in its collapsed state
.navbar-toggler { .navbar-toggler {
padding: $navbar-toggler-padding-y $navbar-toggler-padding-x; padding: $navbar-toggler-padding-y $navbar-toggler-padding-x;
font-size: $navbar-toggler-font-size; font-size: $navbar-toggler-font-size;
line-height: 1; line-height: 1;
background-color: transparent; // remove default button style background-color: transparent; // remove default button style
border: $border-width solid transparent; // remove default button style border: $border-width solid transparent; // remove default button style
@include border-radius($navbar-toggler-border-radius); @include border-radius($navbar-toggler-border-radius);
@include hover-focus { @include hover-focus {
text-decoration: none; text-decoration: none;
} }
// Opinionated: add "hand" cursor to non-disabled .navbar-toggler elements // Opinionated: add "hand" cursor to non-disabled .navbar-toggler elements
&:not(:disabled):not(.disabled) { &:not(:disabled):not(.disabled) {
cursor: pointer; cursor: pointer;
} }
} }
// Keep as a separate element so folks can easily override it with another icon // Keep as a separate element so folks can easily override it with another icon
// or image file as needed. // or image file as needed.
.navbar-toggler-icon { .navbar-toggler-icon {
display: inline-block; display: inline-block;
width: 1.5em; width: 1.5em;
height: 1.5em; height: 1.5em;
vertical-align: middle; vertical-align: middle;
content: ""; content: "";
background: no-repeat center center; background: no-repeat center center;
background-size: 100% 100%; background-size: 100% 100%;
} }
// Generate series of `.navbar-expand-*` responsive classes for configuring // Generate series of `.navbar-expand-*` responsive classes for configuring
// where your navbar collapses. // where your navbar collapses.
.navbar-expand { .navbar-expand {
@each $breakpoint in map-keys($grid-breakpoints) { @each $breakpoint in map-keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints); $next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints); $infix: breakpoint-infix($next, $grid-breakpoints);
&#{$infix} { &#{$infix} {
@include media-breakpoint-down($breakpoint) { @include media-breakpoint-down($breakpoint) {
> .container, > .container,
> .container-fluid { > .container-fluid {
padding-right: 0; padding-right: 0;
padding-left: 0; padding-left: 0;
} }
} }
@include media-breakpoint-up($next) { @include media-breakpoint-up($next) {
flex-flow: row nowrap; flex-flow: row nowrap;
justify-content: flex-start; justify-content: flex-start;
.navbar-nav { .navbar-nav {
flex-direction: row; flex-direction: row;
.dropdown-menu { .dropdown-menu {
position: absolute; position: absolute;
} }
.nav-link { .nav-link {
padding-right: $navbar-nav-link-padding-x; padding-right: $navbar-nav-link-padding-x;
padding-left: $navbar-nav-link-padding-x; padding-left: $navbar-nav-link-padding-x;
} }
} }
// For nesting containers, have to redeclare for alignment purposes // For nesting containers, have to redeclare for alignment purposes
> .container, > .container,
> .container-fluid { > .container-fluid {
flex-wrap: nowrap; flex-wrap: nowrap;
} }
.navbar-collapse { .navbar-collapse {
display: flex !important; // stylelint-disable-line declaration-no-important display: flex !important; // stylelint-disable-line declaration-no-important
// Changes flex-bases to auto because of an IE10 bug // Changes flex-bases to auto because of an IE10 bug
flex-basis: auto; flex-basis: auto;
} }
.navbar-toggler { .navbar-toggler {
display: none; display: none;
} }
} }
} }
} }
} }
// Navbar themes // Navbar themes
// //
// Styles for switching between navbars with light or dark background. // Styles for switching between navbars with light or dark background.
// Dark links against a light background // Dark links against a light background
.navbar-light { .navbar-light {
.navbar-brand { .navbar-brand {
color: $navbar-light-active-color; color: $navbar-light-active-color;
@include hover-focus { @include hover-focus {
color: $navbar-light-active-color; color: $navbar-light-active-color;
} }
} }
.navbar-nav { .navbar-nav {
.nav-link { .nav-link {
color: $navbar-light-color; color: $navbar-light-color;
@include hover-focus { @include hover-focus {
color: $navbar-light-hover-color; color: $navbar-light-hover-color;
} }
&.disabled { &.disabled {
color: $navbar-light-disabled-color; color: $navbar-light-disabled-color;
} }
} }
.show > .nav-link, .show > .nav-link,
.active > .nav-link, .active > .nav-link,
.nav-link.show, .nav-link.show,
.nav-link.active { .nav-link.active {
color: $navbar-light-active-color; color: $navbar-light-active-color;
} }
} }
.navbar-toggler { .navbar-toggler {
color: $navbar-light-color; color: $navbar-light-color;
border-color: $navbar-light-toggler-border-color; border-color: $navbar-light-toggler-border-color;
} }
.navbar-toggler-icon { .navbar-toggler-icon {
background-image: $navbar-light-toggler-icon-bg; background-image: $navbar-light-toggler-icon-bg;
} }
.navbar-text { .navbar-text {
color: $navbar-light-color; color: $navbar-light-color;
a { a {
color: $navbar-light-active-color; color: $navbar-light-active-color;
@include hover-focus { @include hover-focus {
color: $navbar-light-active-color; color: $navbar-light-active-color;
} }
} }
} }
} }
// White links against a dark background // White links against a dark background
.navbar-dark { .navbar-dark {
.navbar-brand { .navbar-brand {
color: $navbar-dark-active-color; color: $navbar-dark-active-color;
@include hover-focus { @include hover-focus {
color: $navbar-dark-active-color; color: $navbar-dark-active-color;
} }
} }
.navbar-nav { .navbar-nav {
.nav-link { .nav-link {
color: $navbar-dark-color; color: $navbar-dark-color;
@include hover-focus { @include hover-focus {
color: $navbar-dark-hover-color; color: $navbar-dark-hover-color;
} }
&.disabled { &.disabled {
color: $navbar-dark-disabled-color; color: $navbar-dark-disabled-color;
} }
} }
.show > .nav-link, .show > .nav-link,
.active > .nav-link, .active > .nav-link,
.nav-link.show, .nav-link.show,
.nav-link.active { .nav-link.active {
color: $navbar-dark-active-color; color: $navbar-dark-active-color;
} }
} }
.navbar-toggler { .navbar-toggler {
color: $navbar-dark-color; color: $navbar-dark-color;
border-color: $navbar-dark-toggler-border-color; border-color: $navbar-dark-toggler-border-color;
} }
.navbar-toggler-icon { .navbar-toggler-icon {
background-image: $navbar-dark-toggler-icon-bg; background-image: $navbar-dark-toggler-icon-bg;
} }
.navbar-text { .navbar-text {
color: $navbar-dark-color; color: $navbar-dark-color;
a { a {
color: $navbar-dark-active-color; color: $navbar-dark-active-color;
@include hover-focus { @include hover-focus {
color: $navbar-dark-active-color; color: $navbar-dark-active-color;
} }
} }
} }
} }

View File

@@ -1,78 +1,78 @@
.pagination { .pagination {
display: flex; display: flex;
@include list-unstyled(); @include list-unstyled();
@include border-radius(); @include border-radius();
} }
.page-link { .page-link {
position: relative; position: relative;
display: block; display: block;
padding: $pagination-padding-y $pagination-padding-x; padding: $pagination-padding-y $pagination-padding-x;
margin-left: -$pagination-border-width; margin-left: -$pagination-border-width;
line-height: $pagination-line-height; line-height: $pagination-line-height;
color: $pagination-color; color: $pagination-color;
background-color: $pagination-bg; background-color: $pagination-bg;
border: $pagination-border-width solid $pagination-border-color; border: $pagination-border-width solid $pagination-border-color;
&:hover { &:hover {
z-index: 2; z-index: 2;
color: $pagination-hover-color; color: $pagination-hover-color;
text-decoration: none; text-decoration: none;
background-color: $pagination-hover-bg; background-color: $pagination-hover-bg;
border-color: $pagination-hover-border-color; border-color: $pagination-hover-border-color;
} }
&:focus { &:focus {
z-index: 2; z-index: 2;
outline: $pagination-focus-outline; outline: $pagination-focus-outline;
box-shadow: $pagination-focus-box-shadow; box-shadow: $pagination-focus-box-shadow;
} }
// Opinionated: add "hand" cursor to non-disabled .page-link elements // Opinionated: add "hand" cursor to non-disabled .page-link elements
&:not(:disabled):not(.disabled) { &:not(:disabled):not(.disabled) {
cursor: pointer; cursor: pointer;
} }
} }
.page-item { .page-item {
&:first-child { &:first-child {
.page-link { .page-link {
margin-left: 0; margin-left: 0;
@include border-left-radius($border-radius); @include border-left-radius($border-radius);
} }
} }
&:last-child { &:last-child {
.page-link { .page-link {
@include border-right-radius($border-radius); @include border-right-radius($border-radius);
} }
} }
&.active .page-link { &.active .page-link {
z-index: 1; z-index: 1;
color: $pagination-active-color; color: $pagination-active-color;
background-color: $pagination-active-bg; background-color: $pagination-active-bg;
border-color: $pagination-active-border-color; border-color: $pagination-active-border-color;
} }
&.disabled .page-link { &.disabled .page-link {
color: $pagination-disabled-color; color: $pagination-disabled-color;
pointer-events: none; pointer-events: none;
// Opinionated: remove the "hand" cursor set previously for .page-link // Opinionated: remove the "hand" cursor set previously for .page-link
cursor: auto; cursor: auto;
background-color: $pagination-disabled-bg; background-color: $pagination-disabled-bg;
border-color: $pagination-disabled-border-color; border-color: $pagination-disabled-border-color;
} }
} }
// //
// Sizing // Sizing
// //
.pagination-lg { .pagination-lg {
@include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg); @include pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg);
} }
.pagination-sm { .pagination-sm {
@include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm); @include pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm);
} }

View File

@@ -1,183 +1,183 @@
.popover { .popover {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
z-index: $zindex-popover; z-index: $zindex-popover;
display: block; display: block;
max-width: $popover-max-width; max-width: $popover-max-width;
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element. // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values. // So reset our font and text properties to avoid inheriting weird values.
@include reset-text(); @include reset-text();
font-size: $popover-font-size; font-size: $popover-font-size;
// Allow breaking very long words so they don't overflow the popover's bounds // Allow breaking very long words so they don't overflow the popover's bounds
word-wrap: break-word; word-wrap: break-word;
background-color: $popover-bg; background-color: $popover-bg;
background-clip: padding-box; background-clip: padding-box;
border: $popover-border-width solid $popover-border-color; border: $popover-border-width solid $popover-border-color;
@include border-radius($popover-border-radius); @include border-radius($popover-border-radius);
@include box-shadow($popover-box-shadow); @include box-shadow($popover-box-shadow);
.arrow { .arrow {
position: absolute; position: absolute;
display: block; display: block;
width: $popover-arrow-width; width: $popover-arrow-width;
height: $popover-arrow-height; height: $popover-arrow-height;
margin: 0 $border-radius-lg; margin: 0 $border-radius-lg;
&::before, &::before,
&::after { &::after {
position: absolute; position: absolute;
display: block; display: block;
content: ""; content: "";
border-color: transparent; border-color: transparent;
border-style: solid; border-style: solid;
} }
} }
} }
.bs-popover-top { .bs-popover-top {
margin-bottom: $popover-arrow-height; margin-bottom: $popover-arrow-height;
.arrow { .arrow {
bottom: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1); bottom: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
} }
.arrow::before, .arrow::before,
.arrow::after { .arrow::after {
border-width: $popover-arrow-height ($popover-arrow-width / 2) 0; border-width: $popover-arrow-height ($popover-arrow-width / 2) 0;
} }
.arrow::before { .arrow::before {
bottom: 0; bottom: 0;
border-top-color: $popover-arrow-outer-color; border-top-color: $popover-arrow-outer-color;
} }
.arrow::after { .arrow::after {
bottom: $popover-border-width; bottom: $popover-border-width;
border-top-color: $popover-arrow-color; border-top-color: $popover-arrow-color;
} }
} }
.bs-popover-right { .bs-popover-right {
margin-left: $popover-arrow-height; margin-left: $popover-arrow-height;
.arrow { .arrow {
left: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1); left: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
width: $popover-arrow-height; width: $popover-arrow-height;
height: $popover-arrow-width; height: $popover-arrow-width;
margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners
} }
.arrow::before, .arrow::before,
.arrow::after { .arrow::after {
border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0; border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0;
} }
.arrow::before { .arrow::before {
left: 0; left: 0;
border-right-color: $popover-arrow-outer-color; border-right-color: $popover-arrow-outer-color;
} }
.arrow::after { .arrow::after {
left: $popover-border-width; left: $popover-border-width;
border-right-color: $popover-arrow-color; border-right-color: $popover-arrow-color;
} }
} }
.bs-popover-bottom { .bs-popover-bottom {
margin-top: $popover-arrow-height; margin-top: $popover-arrow-height;
.arrow { .arrow {
top: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1); top: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
} }
.arrow::before, .arrow::before,
.arrow::after { .arrow::after {
border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2); border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2);
} }
.arrow::before { .arrow::before {
top: 0; top: 0;
border-bottom-color: $popover-arrow-outer-color; border-bottom-color: $popover-arrow-outer-color;
} }
.arrow::after { .arrow::after {
top: $popover-border-width; top: $popover-border-width;
border-bottom-color: $popover-arrow-color; border-bottom-color: $popover-arrow-color;
} }
// This will remove the popover-header's border just below the arrow // This will remove the popover-header's border just below the arrow
.popover-header::before { .popover-header::before {
position: absolute; position: absolute;
top: 0; top: 0;
left: 50%; left: 50%;
display: block; display: block;
width: $popover-arrow-width; width: $popover-arrow-width;
margin-left: ($popover-arrow-width / -2); margin-left: ($popover-arrow-width / -2);
content: ""; content: "";
border-bottom: $popover-border-width solid $popover-header-bg; border-bottom: $popover-border-width solid $popover-header-bg;
} }
} }
.bs-popover-left { .bs-popover-left {
margin-right: $popover-arrow-height; margin-right: $popover-arrow-height;
.arrow { .arrow {
right: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1); right: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1);
width: $popover-arrow-height; width: $popover-arrow-height;
height: $popover-arrow-width; height: $popover-arrow-width;
margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners margin: $border-radius-lg 0; // make sure the arrow does not touch the popover's rounded corners
} }
.arrow::before, .arrow::before,
.arrow::after { .arrow::after {
border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height; border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height;
} }
.arrow::before { .arrow::before {
right: 0; right: 0;
border-left-color: $popover-arrow-outer-color; border-left-color: $popover-arrow-outer-color;
} }
.arrow::after { .arrow::after {
right: $popover-border-width; right: $popover-border-width;
border-left-color: $popover-arrow-color; border-left-color: $popover-arrow-color;
} }
} }
.bs-popover-auto { .bs-popover-auto {
&[x-placement^="top"] { &[x-placement^="top"] {
@extend .bs-popover-top; @extend .bs-popover-top;
} }
&[x-placement^="right"] { &[x-placement^="right"] {
@extend .bs-popover-right; @extend .bs-popover-right;
} }
&[x-placement^="bottom"] { &[x-placement^="bottom"] {
@extend .bs-popover-bottom; @extend .bs-popover-bottom;
} }
&[x-placement^="left"] { &[x-placement^="left"] {
@extend .bs-popover-left; @extend .bs-popover-left;
} }
} }
// Offset the popover to account for the popover arrow // Offset the popover to account for the popover arrow
.popover-header { .popover-header {
padding: $popover-header-padding-y $popover-header-padding-x; padding: $popover-header-padding-y $popover-header-padding-x;
margin-bottom: 0; // Reset the default from Reboot margin-bottom: 0; // Reset the default from Reboot
font-size: $font-size-base; font-size: $font-size-base;
color: $popover-header-color; color: $popover-header-color;
background-color: $popover-header-bg; background-color: $popover-header-bg;
border-bottom: $popover-border-width solid darken($popover-header-bg, 5%); border-bottom: $popover-border-width solid darken($popover-header-bg, 5%);
$offset-border-width: calc(#{$border-radius-lg} - #{$popover-border-width}); $offset-border-width: calc(#{$border-radius-lg} - #{$popover-border-width});
@include border-top-radius($offset-border-width); @include border-top-radius($offset-border-width);
&:empty { &:empty {
display: none; display: none;
} }
} }
.popover-body { .popover-body {
padding: $popover-body-padding-y $popover-body-padding-x; padding: $popover-body-padding-y $popover-body-padding-x;
color: $popover-body-color; color: $popover-body-color;
} }

View File

@@ -1,141 +1,141 @@
// stylelint-disable declaration-no-important, selector-no-qualifying-type // stylelint-disable declaration-no-important, selector-no-qualifying-type
// Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css // Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css
// ========================================================================== // ==========================================================================
// Print styles. // Print styles.
// Inlined to avoid the additional HTTP request: // Inlined to avoid the additional HTTP request:
// https://www.phpied.com/delay-loading-your-print-css/ // https://www.phpied.com/delay-loading-your-print-css/
// ========================================================================== // ==========================================================================
@if $enable-print-styles { @if $enable-print-styles {
@media print { @media print {
*, *,
*::before, *::before,
*::after { *::after {
// Bootstrap specific; comment out `color` and `background` // Bootstrap specific; comment out `color` and `background`
//color: $black !important; // Black prints faster //color: $black !important; // Black prints faster
text-shadow: none !important; text-shadow: none !important;
//background: transparent !important; //background: transparent !important;
box-shadow: none !important; box-shadow: none !important;
} }
a { a {
&:not(.btn) { &:not(.btn) {
text-decoration: underline; text-decoration: underline;
} }
} }
// Bootstrap specific; comment the following selector out // Bootstrap specific; comment the following selector out
//a[href]::after { //a[href]::after {
// content: " (" attr(href) ")"; // content: " (" attr(href) ")";
//} //}
abbr[title]::after { abbr[title]::after {
content: " (" attr(title) ")"; content: " (" attr(title) ")";
} }
// Bootstrap specific; comment the following selector out // Bootstrap specific; comment the following selector out
// //
// Don't show links that are fragment identifiers, // Don't show links that are fragment identifiers,
// or use the `javascript:` pseudo protocol // or use the `javascript:` pseudo protocol
// //
//a[href^="#"]::after, //a[href^="#"]::after,
//a[href^="javascript:"]::after { //a[href^="javascript:"]::after {
// content: ""; // content: "";
//} //}
pre { pre {
white-space: pre-wrap !important; white-space: pre-wrap !important;
} }
pre, pre,
blockquote { blockquote {
border: $border-width solid $gray-500; // Bootstrap custom code; using `$border-width` instead of 1px border: $border-width solid $gray-500; // Bootstrap custom code; using `$border-width` instead of 1px
page-break-inside: avoid; page-break-inside: avoid;
} }
// //
// Printing Tables: // Printing Tables:
// http://css-discuss.incutio.com/wiki/Printing_Tables // http://css-discuss.incutio.com/wiki/Printing_Tables
// //
thead { thead {
display: table-header-group; display: table-header-group;
} }
tr, tr,
img { img {
page-break-inside: avoid; page-break-inside: avoid;
} }
p, p,
h2, h2,
h3 { h3 {
orphans: 3; orphans: 3;
widows: 3; widows: 3;
} }
h2, h2,
h3 { h3 {
page-break-after: avoid; page-break-after: avoid;
} }
// Bootstrap specific changes start // Bootstrap specific changes start
// Specify a size and min-width to make printing closer across browsers. // Specify a size and min-width to make printing closer across browsers.
// We don't set margin here because it breaks `size` in Chrome. We also // We don't set margin here because it breaks `size` in Chrome. We also
// don't use `!important` on `size` as it breaks in Chrome. // don't use `!important` on `size` as it breaks in Chrome.
@page { @page {
size: $print-page-size; size: $print-page-size;
} }
body { body {
min-width: $print-body-min-width !important; min-width: $print-body-min-width !important;
} }
.container { .container {
min-width: $print-body-min-width !important; min-width: $print-body-min-width !important;
} }
// Bootstrap components // Bootstrap components
.navbar { .navbar {
display: none; display: none;
} }
.badge { .badge {
border: $border-width solid $black; border: $border-width solid $black;
} }
.table { .table {
border-collapse: collapse !important; border-collapse: collapse !important;
td, td,
th { th {
background-color: $white !important; background-color: $white !important;
} }
} }
.table-bordered { .table-bordered {
th, th,
td { td {
border: 1px solid $gray-300 !important; border: 1px solid $gray-300 !important;
} }
} }
.table-dark { .table-dark {
color: inherit; color: inherit;
th, th,
td, td,
thead th, thead th,
tbody + tbody { tbody + tbody {
border-color: $table-border-color; border-color: $table-border-color;
} }
} }
.table .thead-dark th { .table .thead-dark th {
color: inherit; color: inherit;
border-color: $table-border-color; border-color: $table-border-color;
} }
// Bootstrap specific changes end // Bootstrap specific changes end
} }
} }

View File

@@ -1,34 +1,34 @@
@keyframes progress-bar-stripes { @keyframes progress-bar-stripes {
from { background-position: $progress-height 0; } from { background-position: $progress-height 0; }
to { background-position: 0 0; } to { background-position: 0 0; }
} }
.progress { .progress {
display: flex; display: flex;
height: $progress-height; height: $progress-height;
overflow: hidden; // force rounded corners by cropping it overflow: hidden; // force rounded corners by cropping it
font-size: $progress-font-size; font-size: $progress-font-size;
background-color: $progress-bg; background-color: $progress-bg;
@include border-radius($progress-border-radius); @include border-radius($progress-border-radius);
@include box-shadow($progress-box-shadow); @include box-shadow($progress-box-shadow);
} }
.progress-bar { .progress-bar {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
color: $progress-bar-color; color: $progress-bar-color;
text-align: center; text-align: center;
white-space: nowrap; white-space: nowrap;
background-color: $progress-bar-bg; background-color: $progress-bar-bg;
@include transition($progress-bar-transition); @include transition($progress-bar-transition);
} }
.progress-bar-striped { .progress-bar-striped {
@include gradient-striped(); @include gradient-striped();
background-size: $progress-height $progress-height; background-size: $progress-height $progress-height;
} }
.progress-bar-animated { .progress-bar-animated {
animation: progress-bar-stripes $progress-bar-animation-timing; animation: progress-bar-stripes $progress-bar-animation-timing;
} }

View File

@@ -1,480 +1,480 @@
// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix // stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix
// Reboot // Reboot
// //
// Normalization of HTML elements, manually forked from Normalize.css to remove // Normalization of HTML elements, manually forked from Normalize.css to remove
// styles targeting irrelevant browsers while applying new styles. // styles targeting irrelevant browsers while applying new styles.
// //
// Normalize is licensed MIT. https://github.com/necolas/normalize.css // Normalize is licensed MIT. https://github.com/necolas/normalize.css
// Document // Document
// //
// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`. // 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
// 2. Change the default font family in all browsers. // 2. Change the default font family in all browsers.
// 3. Correct the line height in all browsers. // 3. Correct the line height in all browsers.
// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS. // 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.
// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so // 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so
// we force a non-overlapping, non-auto-hiding scrollbar to counteract. // we force a non-overlapping, non-auto-hiding scrollbar to counteract.
// 6. Change the default tap highlight to be completely transparent in iOS. // 6. Change the default tap highlight to be completely transparent in iOS.
*, *,
*::before, *::before,
*::after { *::after {
box-sizing: border-box; // 1 box-sizing: border-box; // 1
} }
html { html {
font-family: sans-serif; // 2 font-family: sans-serif; // 2
line-height: 1.15; // 3 line-height: 1.15; // 3
-webkit-text-size-adjust: 100%; // 4 -webkit-text-size-adjust: 100%; // 4
-ms-text-size-adjust: 100%; // 4 -ms-text-size-adjust: 100%; // 4
-ms-overflow-style: scrollbar; // 5 -ms-overflow-style: scrollbar; // 5
-webkit-tap-highlight-color: rgba($black, 0); // 6 -webkit-tap-highlight-color: rgba($black, 0); // 6
} }
// IE10+ doesn't honor `<meta name="viewport">` in some cases. // IE10+ doesn't honor `<meta name="viewport">` in some cases.
@at-root { @at-root {
@-ms-viewport { @-ms-viewport {
width: device-width; width: device-width;
} }
} }
// stylelint-disable selector-list-comma-newline-after // stylelint-disable selector-list-comma-newline-after
// Shim for "new" HTML5 structural elements to display correctly (IE10, older browsers) // Shim for "new" HTML5 structural elements to display correctly (IE10, older browsers)
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { article, aside, figcaption, figure, footer, header, hgroup, main, nav, section {
display: block; display: block;
} }
// stylelint-enable selector-list-comma-newline-after // stylelint-enable selector-list-comma-newline-after
// Body // Body
// //
// 1. Remove the margin in all browsers. // 1. Remove the margin in all browsers.
// 2. As a best practice, apply a default `background-color`. // 2. As a best practice, apply a default `background-color`.
// 3. Set an explicit initial text-align value so that we can later use the // 3. Set an explicit initial text-align value so that we can later use the
// the `inherit` value on things like `<th>` elements. // the `inherit` value on things like `<th>` elements.
body { body {
margin: 0; // 1 margin: 0; // 1
font-family: $font-family-base; font-family: $font-family-base;
font-size: $font-size-base; font-size: $font-size-base;
font-weight: $font-weight-base; font-weight: $font-weight-base;
line-height: $line-height-base; line-height: $line-height-base;
color: $body-color; color: $body-color;
text-align: left; // 3 text-align: left; // 3
background-color: $body-bg; // 2 background-color: $body-bg; // 2
} }
// Suppress the focus outline on elements that cannot be accessed via keyboard. // Suppress the focus outline on elements that cannot be accessed via keyboard.
// This prevents an unwanted focus outline from appearing around elements that // This prevents an unwanted focus outline from appearing around elements that
// might still respond to pointer events. // might still respond to pointer events.
// //
// Credit: https://github.com/suitcss/base // Credit: https://github.com/suitcss/base
[tabindex="-1"]:focus { [tabindex="-1"]:focus {
outline: 0 !important; outline: 0 !important;
} }
// Content grouping // Content grouping
// //
// 1. Add the correct box sizing in Firefox. // 1. Add the correct box sizing in Firefox.
// 2. Show the overflow in Edge and IE. // 2. Show the overflow in Edge and IE.
hr { hr {
box-sizing: content-box; // 1 box-sizing: content-box; // 1
height: 0; // 1 height: 0; // 1
overflow: visible; // 2 overflow: visible; // 2
} }
// //
// Typography // Typography
// //
// Remove top margins from headings // Remove top margins from headings
// //
// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top // By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top
// margin for easier control within type scales as it avoids margin collapsing. // margin for easier control within type scales as it avoids margin collapsing.
// stylelint-disable selector-list-comma-newline-after // stylelint-disable selector-list-comma-newline-after
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
margin-top: 0; margin-top: 0;
margin-bottom: $headings-margin-bottom; margin-bottom: $headings-margin-bottom;
} }
// stylelint-enable selector-list-comma-newline-after // stylelint-enable selector-list-comma-newline-after
// Reset margins on paragraphs // Reset margins on paragraphs
// //
// Similarly, the top margin on `<p>`s get reset. However, we also reset the // Similarly, the top margin on `<p>`s get reset. However, we also reset the
// bottom margin to use `rem` units instead of `em`. // bottom margin to use `rem` units instead of `em`.
p { p {
margin-top: 0; margin-top: 0;
margin-bottom: $paragraph-margin-bottom; margin-bottom: $paragraph-margin-bottom;
} }
// Abbreviations // Abbreviations
// //
// 1. Remove the bottom border in Firefox 39-. // 1. Remove the bottom border in Firefox 39-.
// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. // 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
// 3. Add explicit cursor to indicate changed behavior. // 3. Add explicit cursor to indicate changed behavior.
// 4. Duplicate behavior to the data-* attribute for our tooltip plugin // 4. Duplicate behavior to the data-* attribute for our tooltip plugin
abbr[title], abbr[title],
abbr[data-original-title] { // 4 abbr[data-original-title] { // 4
text-decoration: underline; // 2 text-decoration: underline; // 2
text-decoration: underline dotted; // 2 text-decoration: underline dotted; // 2
cursor: help; // 3 cursor: help; // 3
border-bottom: 0; // 1 border-bottom: 0; // 1
} }
address { address {
margin-bottom: 1rem; margin-bottom: 1rem;
font-style: normal; font-style: normal;
line-height: inherit; line-height: inherit;
} }
ol, ol,
ul, ul,
dl { dl {
margin-top: 0; margin-top: 0;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
ol ol, ol ol,
ul ul, ul ul,
ol ul, ol ul,
ul ol { ul ol {
margin-bottom: 0; margin-bottom: 0;
} }
dt { dt {
font-weight: $dt-font-weight; font-weight: $dt-font-weight;
} }
dd { dd {
margin-bottom: .5rem; margin-bottom: .5rem;
margin-left: 0; // Undo browser default margin-left: 0; // Undo browser default
} }
blockquote { blockquote {
margin: 0 0 1rem; margin: 0 0 1rem;
} }
dfn { dfn {
font-style: italic; // Add the correct font style in Android 4.3- font-style: italic; // Add the correct font style in Android 4.3-
} }
// stylelint-disable font-weight-notation // stylelint-disable font-weight-notation
b, b,
strong { strong {
font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari
} }
// stylelint-enable font-weight-notation // stylelint-enable font-weight-notation
small { small {
font-size: 80%; // Add the correct font size in all browsers font-size: 80%; // Add the correct font size in all browsers
} }
// //
// Prevent `sub` and `sup` elements from affecting the line height in // Prevent `sub` and `sup` elements from affecting the line height in
// all browsers. // all browsers.
// //
sub, sub,
sup { sup {
position: relative; position: relative;
font-size: 75%; font-size: 75%;
line-height: 0; line-height: 0;
vertical-align: baseline; vertical-align: baseline;
} }
sub { bottom: -.25em; } sub { bottom: -.25em; }
sup { top: -.5em; } sup { top: -.5em; }
// //
// Links // Links
// //
a { a {
color: $link-color; color: $link-color;
text-decoration: $link-decoration; text-decoration: $link-decoration;
background-color: transparent; // Remove the gray background on active links in IE 10. background-color: transparent; // Remove the gray background on active links in IE 10.
-webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+. -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.
@include hover { @include hover {
color: $link-hover-color; color: $link-hover-color;
text-decoration: $link-hover-decoration; text-decoration: $link-hover-decoration;
} }
} }
// And undo these styles for placeholder links/named anchors (without href) // And undo these styles for placeholder links/named anchors (without href)
// which have not been made explicitly keyboard-focusable (without tabindex). // which have not been made explicitly keyboard-focusable (without tabindex).
// It would be more straightforward to just use a[href] in previous block, but that // It would be more straightforward to just use a[href] in previous block, but that
// causes specificity issues in many other styles that are too complex to fix. // causes specificity issues in many other styles that are too complex to fix.
// See https://github.com/twbs/bootstrap/issues/19402 // See https://github.com/twbs/bootstrap/issues/19402
a:not([href]):not([tabindex]) { a:not([href]):not([tabindex]) {
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
@include hover-focus { @include hover-focus {
color: inherit; color: inherit;
text-decoration: none; text-decoration: none;
} }
&:focus { &:focus {
outline: 0; outline: 0;
} }
} }
// //
// Code // Code
// //
pre, pre,
code, code,
kbd, kbd,
samp { samp {
font-family: $font-family-monospace; font-family: $font-family-monospace;
font-size: 1em; // Correct the odd `em` font sizing in all browsers. font-size: 1em; // Correct the odd `em` font sizing in all browsers.
} }
pre { pre {
// Remove browser default top margin // Remove browser default top margin
margin-top: 0; margin-top: 0;
// Reset browser default of `1em` to use `rem`s // Reset browser default of `1em` to use `rem`s
margin-bottom: 1rem; margin-bottom: 1rem;
// Don't allow content to break outside // Don't allow content to break outside
overflow: auto; overflow: auto;
// We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so
// we force a non-overlapping, non-auto-hiding scrollbar to counteract. // we force a non-overlapping, non-auto-hiding scrollbar to counteract.
-ms-overflow-style: scrollbar; -ms-overflow-style: scrollbar;
} }
// //
// Figures // Figures
// //
figure { figure {
// Apply a consistent margin strategy (matches our type styles). // Apply a consistent margin strategy (matches our type styles).
margin: 0 0 1rem; margin: 0 0 1rem;
} }
// //
// Images and content // Images and content
// //
img { img {
vertical-align: middle; vertical-align: middle;
border-style: none; // Remove the border on images inside links in IE 10-. border-style: none; // Remove the border on images inside links in IE 10-.
} }
svg:not(:root) { svg:not(:root) {
overflow: hidden; // Hide the overflow in IE overflow: hidden; // Hide the overflow in IE
} }
// //
// Tables // Tables
// //
table { table {
border-collapse: collapse; // Prevent double borders border-collapse: collapse; // Prevent double borders
} }
caption { caption {
padding-top: $table-cell-padding; padding-top: $table-cell-padding;
padding-bottom: $table-cell-padding; padding-bottom: $table-cell-padding;
color: $table-caption-color; color: $table-caption-color;
text-align: left; text-align: left;
caption-side: bottom; caption-side: bottom;
} }
th { th {
// Matches default `<td>` alignment by inheriting from the `<body>`, or the // Matches default `<td>` alignment by inheriting from the `<body>`, or the
// closest parent with a set `text-align`. // closest parent with a set `text-align`.
text-align: inherit; text-align: inherit;
} }
// //
// Forms // Forms
// //
label { label {
// Allow labels to use `margin` for spacing. // Allow labels to use `margin` for spacing.
display: inline-block; display: inline-block;
margin-bottom: $label-margin-bottom; margin-bottom: $label-margin-bottom;
} }
// Remove the default `border-radius` that macOS Chrome adds. // Remove the default `border-radius` that macOS Chrome adds.
// //
// Details at https://github.com/twbs/bootstrap/issues/24093 // Details at https://github.com/twbs/bootstrap/issues/24093
button { button {
border-radius: 0; border-radius: 0;
} }
// Work around a Firefox/IE bug where the transparent `button` background // Work around a Firefox/IE bug where the transparent `button` background
// results in a loss of the default `button` focus styles. // results in a loss of the default `button` focus styles.
// //
// Credit: https://github.com/suitcss/base/ // Credit: https://github.com/suitcss/base/
button:focus { button:focus {
outline: 1px dotted; outline: 1px dotted;
outline: 5px auto -webkit-focus-ring-color; outline: 5px auto -webkit-focus-ring-color;
} }
input, input,
button, button,
select, select,
optgroup, optgroup,
textarea { textarea {
margin: 0; // Remove the margin in Firefox and Safari margin: 0; // Remove the margin in Firefox and Safari
font-family: inherit; font-family: inherit;
font-size: inherit; font-size: inherit;
line-height: inherit; line-height: inherit;
} }
button, button,
input { input {
overflow: visible; // Show the overflow in Edge overflow: visible; // Show the overflow in Edge
} }
button, button,
select { select {
text-transform: none; // Remove the inheritance of text transform in Firefox text-transform: none; // Remove the inheritance of text transform in Firefox
} }
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video` // 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
// controls in Android 4. // controls in Android 4.
// 2. Correct the inability to style clickable types in iOS and Safari. // 2. Correct the inability to style clickable types in iOS and Safari.
button, button,
html [type="button"], // 1 html [type="button"], // 1
[type="reset"], [type="reset"],
[type="submit"] { [type="submit"] {
-webkit-appearance: button; // 2 -webkit-appearance: button; // 2
} }
// Remove inner border and padding from Firefox, but don't restore the outline like Normalize. // Remove inner border and padding from Firefox, but don't restore the outline like Normalize.
button::-moz-focus-inner, button::-moz-focus-inner,
[type="button"]::-moz-focus-inner, [type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner { [type="submit"]::-moz-focus-inner {
padding: 0; padding: 0;
border-style: none; border-style: none;
} }
input[type="radio"], input[type="radio"],
input[type="checkbox"] { input[type="checkbox"] {
box-sizing: border-box; // 1. Add the correct box sizing in IE 10- box-sizing: border-box; // 1. Add the correct box sizing in IE 10-
padding: 0; // 2. Remove the padding in IE 10- padding: 0; // 2. Remove the padding in IE 10-
} }
input[type="date"], input[type="date"],
input[type="time"], input[type="time"],
input[type="datetime-local"], input[type="datetime-local"],
input[type="month"] { input[type="month"] {
// Remove the default appearance of temporal inputs to avoid a Mobile Safari // Remove the default appearance of temporal inputs to avoid a Mobile Safari
// bug where setting a custom line-height prevents text from being vertically // bug where setting a custom line-height prevents text from being vertically
// centered within the input. // centered within the input.
// See https://bugs.webkit.org/show_bug.cgi?id=139848 // See https://bugs.webkit.org/show_bug.cgi?id=139848
// and https://github.com/twbs/bootstrap/issues/11266 // and https://github.com/twbs/bootstrap/issues/11266
-webkit-appearance: listbox; -webkit-appearance: listbox;
} }
textarea { textarea {
overflow: auto; // Remove the default vertical scrollbar in IE. overflow: auto; // Remove the default vertical scrollbar in IE.
// Textareas should really only resize vertically so they don't break their (horizontal) containers. // Textareas should really only resize vertically so they don't break their (horizontal) containers.
resize: vertical; resize: vertical;
} }
fieldset { fieldset {
// Browsers set a default `min-width: min-content;` on fieldsets, // Browsers set a default `min-width: min-content;` on fieldsets,
// unlike e.g. `<div>`s, which have `min-width: 0;` by default. // unlike e.g. `<div>`s, which have `min-width: 0;` by default.
// So we reset that to ensure fieldsets behave more like a standard block element. // So we reset that to ensure fieldsets behave more like a standard block element.
// See https://github.com/twbs/bootstrap/issues/12359 // See https://github.com/twbs/bootstrap/issues/12359
// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
min-width: 0; min-width: 0;
// Reset the default outline behavior of fieldsets so they don't affect page layout. // Reset the default outline behavior of fieldsets so they don't affect page layout.
padding: 0; padding: 0;
margin: 0; margin: 0;
border: 0; border: 0;
} }
// 1. Correct the text wrapping in Edge and IE. // 1. Correct the text wrapping in Edge and IE.
// 2. Correct the color inheritance from `fieldset` elements in IE. // 2. Correct the color inheritance from `fieldset` elements in IE.
legend { legend {
display: block; display: block;
width: 100%; width: 100%;
max-width: 100%; // 1 max-width: 100%; // 1
padding: 0; padding: 0;
margin-bottom: .5rem; margin-bottom: .5rem;
font-size: 1.5rem; font-size: 1.5rem;
line-height: inherit; line-height: inherit;
color: inherit; // 2 color: inherit; // 2
white-space: normal; // 1 white-space: normal; // 1
} }
progress { progress {
vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera. vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.
} }
// Correct the cursor style of increment and decrement buttons in Chrome. // Correct the cursor style of increment and decrement buttons in Chrome.
[type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button { [type="number"]::-webkit-outer-spin-button {
height: auto; height: auto;
} }
[type="search"] { [type="search"] {
// This overrides the extra rounded corners on search inputs in iOS so that our // This overrides the extra rounded corners on search inputs in iOS so that our
// `.form-control` class can properly style them. Note that this cannot simply // `.form-control` class can properly style them. Note that this cannot simply
// be added to `.form-control` as it's not specific enough. For details, see // be added to `.form-control` as it's not specific enough. For details, see
// https://github.com/twbs/bootstrap/issues/11586. // https://github.com/twbs/bootstrap/issues/11586.
outline-offset: -2px; // 2. Correct the outline style in Safari. outline-offset: -2px; // 2. Correct the outline style in Safari.
-webkit-appearance: none; -webkit-appearance: none;
} }
// //
// Remove the inner padding and cancel buttons in Chrome and Safari on macOS. // Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
// //
[type="search"]::-webkit-search-cancel-button, [type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration { [type="search"]::-webkit-search-decoration {
-webkit-appearance: none; -webkit-appearance: none;
} }
// //
// 1. Correct the inability to style clickable types in iOS and Safari. // 1. Correct the inability to style clickable types in iOS and Safari.
// 2. Change font properties to `inherit` in Safari. // 2. Change font properties to `inherit` in Safari.
// //
::-webkit-file-upload-button { ::-webkit-file-upload-button {
font: inherit; // 2 font: inherit; // 2
-webkit-appearance: button; // 1 -webkit-appearance: button; // 1
} }
// //
// Correct element displays // Correct element displays
// //
output { output {
display: inline-block; display: inline-block;
} }
summary { summary {
display: list-item; // Add the correct display in all browsers display: list-item; // Add the correct display in all browsers
cursor: pointer; cursor: pointer;
} }
template { template {
display: none; // Add the correct display in IE display: none; // Add the correct display in IE
} }
// Always hide an element with the `hidden` HTML attribute (from PureCSS). // Always hide an element with the `hidden` HTML attribute (from PureCSS).
// Needed for proper display in IE 10-. // Needed for proper display in IE 10-.
[hidden] { [hidden] {
display: none !important; display: none !important;
} }

View File

@@ -1,19 +1,19 @@
:root { :root {
// Custom variable values only support SassScript inside `#{}`. // Custom variable values only support SassScript inside `#{}`.
@each $color, $value in $colors { @each $color, $value in $colors {
--#{$color}: #{$value}; --#{$color}: #{$value};
} }
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
--#{$color}: #{$value}; --#{$color}: #{$value};
} }
@each $bp, $value in $grid-breakpoints { @each $bp, $value in $grid-breakpoints {
--breakpoint-#{$bp}: #{$value}; --breakpoint-#{$bp}: #{$value};
} }
// Use `inspect` for lists so that quoted items keep the quotes. // Use `inspect` for lists so that quoted items keep the quotes.
// See https://github.com/sass/sass/issues/2383#issuecomment-336349172 // See https://github.com/sass/sass/issues/2383#issuecomment-336349172
--font-family-sans-serif: #{inspect($font-family-sans-serif)}; --font-family-sans-serif: #{inspect($font-family-sans-serif)};
--font-family-monospace: #{inspect($font-family-monospace)}; --font-family-monospace: #{inspect($font-family-monospace)};
} }

View File

@@ -1,188 +1,188 @@
// //
// Basic Bootstrap table // Basic Bootstrap table
// //
.table { .table {
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
margin-bottom: $spacer; margin-bottom: $spacer;
background-color: $table-bg; // Reset for nesting within parents with `background-color`. background-color: $table-bg; // Reset for nesting within parents with `background-color`.
th, th,
td { td {
padding: $table-cell-padding; padding: $table-cell-padding;
vertical-align: top; vertical-align: top;
border-top: $table-border-width solid $table-border-color; border-top: $table-border-width solid $table-border-color;
} }
thead th { thead th {
vertical-align: bottom; vertical-align: bottom;
border-bottom: (2 * $table-border-width) solid $table-border-color; border-bottom: (2 * $table-border-width) solid $table-border-color;
} }
tbody + tbody { tbody + tbody {
border-top: (2 * $table-border-width) solid $table-border-color; border-top: (2 * $table-border-width) solid $table-border-color;
} }
.table { .table {
background-color: $body-bg; background-color: $body-bg;
} }
} }
// //
// Condensed table w/ half padding // Condensed table w/ half padding
// //
.table-sm { .table-sm {
th, th,
td { td {
padding: $table-cell-padding-sm; padding: $table-cell-padding-sm;
} }
} }
// Border versions // Border versions
// //
// Add or remove borders all around the table and between all the columns. // Add or remove borders all around the table and between all the columns.
.table-bordered { .table-bordered {
border: $table-border-width solid $table-border-color; border: $table-border-width solid $table-border-color;
th, th,
td { td {
border: $table-border-width solid $table-border-color; border: $table-border-width solid $table-border-color;
} }
thead { thead {
th, th,
td { td {
border-bottom-width: (2 * $table-border-width); border-bottom-width: (2 * $table-border-width);
} }
} }
} }
.table-borderless { .table-borderless {
th, th,
td, td,
thead th, thead th,
tbody + tbody { tbody + tbody {
border: 0; border: 0;
} }
} }
// Zebra-striping // Zebra-striping
// //
// Default zebra-stripe styles (alternating gray and transparent backgrounds) // Default zebra-stripe styles (alternating gray and transparent backgrounds)
.table-striped { .table-striped {
tbody tr:nth-of-type(#{$table-striped-order}) { tbody tr:nth-of-type(#{$table-striped-order}) {
background-color: $table-accent-bg; background-color: $table-accent-bg;
} }
} }
// Hover effect // Hover effect
// //
// Placed here since it has to come after the potential zebra striping // Placed here since it has to come after the potential zebra striping
.table-hover { .table-hover {
tbody tr { tbody tr {
@include hover { @include hover {
background-color: $table-hover-bg; background-color: $table-hover-bg;
} }
} }
} }
// Table backgrounds // Table backgrounds
// //
// Exact selectors below required to override `.table-striped` and prevent // Exact selectors below required to override `.table-striped` and prevent
// inheritance to nested tables. // inheritance to nested tables.
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
@include table-row-variant($color, theme-color-level($color, -9)); @include table-row-variant($color, theme-color-level($color, -9));
} }
@include table-row-variant(active, $table-active-bg); @include table-row-variant(active, $table-active-bg);
// Dark styles // Dark styles
// //
// Same table markup, but inverted color scheme: dark background and light text. // Same table markup, but inverted color scheme: dark background and light text.
// stylelint-disable-next-line no-duplicate-selectors // stylelint-disable-next-line no-duplicate-selectors
.table { .table {
.thead-dark { .thead-dark {
th { th {
color: $table-dark-color; color: $table-dark-color;
background-color: $table-dark-bg; background-color: $table-dark-bg;
border-color: $table-dark-border-color; border-color: $table-dark-border-color;
} }
} }
.thead-light { .thead-light {
th { th {
color: $table-head-color; color: $table-head-color;
background-color: $table-head-bg; background-color: $table-head-bg;
border-color: $table-border-color; border-color: $table-border-color;
} }
} }
} }
.table-dark { .table-dark {
color: $table-dark-color; color: $table-dark-color;
background-color: $table-dark-bg; background-color: $table-dark-bg;
th, th,
td, td,
thead th { thead th {
border-color: $table-dark-border-color; border-color: $table-dark-border-color;
} }
&.table-bordered { &.table-bordered {
border: 0; border: 0;
} }
&.table-striped { &.table-striped {
tbody tr:nth-of-type(odd) { tbody tr:nth-of-type(odd) {
background-color: $table-dark-accent-bg; background-color: $table-dark-accent-bg;
} }
} }
&.table-hover { &.table-hover {
tbody tr { tbody tr {
@include hover { @include hover {
background-color: $table-dark-hover-bg; background-color: $table-dark-hover-bg;
} }
} }
} }
} }
// Responsive tables // Responsive tables
// //
// Generate series of `.table-responsive-*` classes for configuring the screen // Generate series of `.table-responsive-*` classes for configuring the screen
// size of where your table will overflow. // size of where your table will overflow.
.table-responsive { .table-responsive {
@each $breakpoint in map-keys($grid-breakpoints) { @each $breakpoint in map-keys($grid-breakpoints) {
$next: breakpoint-next($breakpoint, $grid-breakpoints); $next: breakpoint-next($breakpoint, $grid-breakpoints);
$infix: breakpoint-infix($next, $grid-breakpoints); $infix: breakpoint-infix($next, $grid-breakpoints);
&#{$infix} { &#{$infix} {
@include media-breakpoint-down($breakpoint) { @include media-breakpoint-down($breakpoint) {
display: block; display: block;
width: 100%; width: 100%;
overflow-x: auto; overflow-x: auto;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar; // See https://github.com/twbs/bootstrap/pull/10057 -ms-overflow-style: -ms-autohiding-scrollbar; // See https://github.com/twbs/bootstrap/pull/10057
// Prevent double border on horizontal scroll due to use of `display: block;` // Prevent double border on horizontal scroll due to use of `display: block;`
> .table-bordered { > .table-bordered {
border: 0; border: 0;
} }
} }
} }
} }
} }

View File

@@ -1,115 +1,115 @@
// Base class // Base class
.tooltip { .tooltip {
position: absolute; position: absolute;
z-index: $zindex-tooltip; z-index: $zindex-tooltip;
display: block; display: block;
margin: $tooltip-margin; margin: $tooltip-margin;
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element. // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values. // So reset our font and text properties to avoid inheriting weird values.
@include reset-text(); @include reset-text();
font-size: $tooltip-font-size; font-size: $tooltip-font-size;
// Allow breaking very long words so they don't overflow the tooltip's bounds // Allow breaking very long words so they don't overflow the tooltip's bounds
word-wrap: break-word; word-wrap: break-word;
opacity: 0; opacity: 0;
&.show { opacity: $tooltip-opacity; } &.show { opacity: $tooltip-opacity; }
.arrow { .arrow {
position: absolute; position: absolute;
display: block; display: block;
width: $tooltip-arrow-width; width: $tooltip-arrow-width;
height: $tooltip-arrow-height; height: $tooltip-arrow-height;
&::before { &::before {
position: absolute; position: absolute;
content: ""; content: "";
border-color: transparent; border-color: transparent;
border-style: solid; border-style: solid;
} }
} }
} }
.bs-tooltip-top { .bs-tooltip-top {
padding: $tooltip-arrow-height 0; padding: $tooltip-arrow-height 0;
.arrow { .arrow {
bottom: 0; bottom: 0;
&::before { &::before {
top: 0; top: 0;
border-width: $tooltip-arrow-height ($tooltip-arrow-width / 2) 0; border-width: $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;
border-top-color: $tooltip-arrow-color; border-top-color: $tooltip-arrow-color;
} }
} }
} }
.bs-tooltip-right { .bs-tooltip-right {
padding: 0 $tooltip-arrow-height; padding: 0 $tooltip-arrow-height;
.arrow { .arrow {
left: 0; left: 0;
width: $tooltip-arrow-height; width: $tooltip-arrow-height;
height: $tooltip-arrow-width; height: $tooltip-arrow-width;
&::before { &::before {
right: 0; right: 0;
border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0; border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0;
border-right-color: $tooltip-arrow-color; border-right-color: $tooltip-arrow-color;
} }
} }
} }
.bs-tooltip-bottom { .bs-tooltip-bottom {
padding: $tooltip-arrow-height 0; padding: $tooltip-arrow-height 0;
.arrow { .arrow {
top: 0; top: 0;
&::before { &::before {
bottom: 0; bottom: 0;
border-width: 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height; border-width: 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;
border-bottom-color: $tooltip-arrow-color; border-bottom-color: $tooltip-arrow-color;
} }
} }
} }
.bs-tooltip-left { .bs-tooltip-left {
padding: 0 $tooltip-arrow-height; padding: 0 $tooltip-arrow-height;
.arrow { .arrow {
right: 0; right: 0;
width: $tooltip-arrow-height; width: $tooltip-arrow-height;
height: $tooltip-arrow-width; height: $tooltip-arrow-width;
&::before { &::before {
left: 0; left: 0;
border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height; border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height;
border-left-color: $tooltip-arrow-color; border-left-color: $tooltip-arrow-color;
} }
} }
} }
.bs-tooltip-auto { .bs-tooltip-auto {
&[x-placement^="top"] { &[x-placement^="top"] {
@extend .bs-tooltip-top; @extend .bs-tooltip-top;
} }
&[x-placement^="right"] { &[x-placement^="right"] {
@extend .bs-tooltip-right; @extend .bs-tooltip-right;
} }
&[x-placement^="bottom"] { &[x-placement^="bottom"] {
@extend .bs-tooltip-bottom; @extend .bs-tooltip-bottom;
} }
&[x-placement^="left"] { &[x-placement^="left"] {
@extend .bs-tooltip-left; @extend .bs-tooltip-left;
} }
} }
// Wrapper for the tooltip content // Wrapper for the tooltip content
.tooltip-inner { .tooltip-inner {
max-width: $tooltip-max-width; max-width: $tooltip-max-width;
padding: $tooltip-padding-y $tooltip-padding-x; padding: $tooltip-padding-y $tooltip-padding-x;
color: $tooltip-color; color: $tooltip-color;
text-align: center; text-align: center;
background-color: $tooltip-bg; background-color: $tooltip-bg;
@include border-radius($tooltip-border-radius); @include border-radius($tooltip-border-radius);
} }

View File

@@ -1,22 +1,22 @@
// stylelint-disable selector-no-qualifying-type // stylelint-disable selector-no-qualifying-type
.fade { .fade {
@include transition($transition-fade); @include transition($transition-fade);
&:not(.show) { &:not(.show) {
opacity: 0; opacity: 0;
} }
} }
.collapse { .collapse {
&:not(.show) { &:not(.show) {
display: none; display: none;
} }
} }
.collapsing { .collapsing {
position: relative; position: relative;
height: 0; height: 0;
overflow: hidden; overflow: hidden;
@include transition($transition-collapse); @include transition($transition-collapse);
} }

View File

@@ -1,15 +1,15 @@
@import "utilities/align"; @import "utilities/align";
@import "utilities/background"; @import "utilities/background";
@import "utilities/borders"; @import "utilities/borders";
@import "utilities/clearfix"; @import "utilities/clearfix";
@import "utilities/display"; @import "utilities/display";
@import "utilities/embed"; @import "utilities/embed";
@import "utilities/flex"; @import "utilities/flex";
@import "utilities/float"; @import "utilities/float";
@import "utilities/position"; @import "utilities/position";
@import "utilities/screenreaders"; @import "utilities/screenreaders";
@import "utilities/shadows"; @import "utilities/shadows";
@import "utilities/sizing"; @import "utilities/sizing";
@import "utilities/spacing"; @import "utilities/spacing";
@import "utilities/text"; @import "utilities/text";
@import "utilities/visibility"; @import "utilities/visibility";

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +1,32 @@
/*! /*!
* Bootstrap Grid v4.1.1 (https://getbootstrap.com/) * Bootstrap Grid v4.1.1 (https://getbootstrap.com/)
* Copyright 2011-2018 The Bootstrap Authors * Copyright 2011-2018 The Bootstrap Authors
* Copyright 2011-2018 Twitter, Inc. * Copyright 2011-2018 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/ */
@at-root { @at-root {
@-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix
} }
html { html {
box-sizing: border-box; box-sizing: border-box;
-ms-overflow-style: scrollbar; -ms-overflow-style: scrollbar;
} }
*, *,
*::before, *::before,
*::after { *::after {
box-sizing: inherit; box-sizing: inherit;
} }
@import "functions"; @import "functions";
@import "variables"; @import "variables";
@import "mixins/breakpoints"; @import "mixins/breakpoints";
@import "mixins/grid-framework"; @import "mixins/grid-framework";
@import "mixins/grid"; @import "mixins/grid";
@import "grid"; @import "grid";
@import "utilities/display"; @import "utilities/display";
@import "utilities/flex"; @import "utilities/flex";

View File

@@ -1,12 +1,12 @@
/*! /*!
* Bootstrap Reboot v4.1.1 (https://getbootstrap.com/) * Bootstrap Reboot v4.1.1 (https://getbootstrap.com/)
* Copyright 2011-2018 The Bootstrap Authors * Copyright 2011-2018 The Bootstrap Authors
* Copyright 2011-2018 Twitter, Inc. * Copyright 2011-2018 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
*/ */
@import "functions"; @import "functions";
@import "variables"; @import "variables";
@import "mixins"; @import "mixins";
@import "reboot"; @import "reboot";

View File

@@ -1,42 +1,42 @@
/*! /*!
* Bootstrap v4.1.1 (https://getbootstrap.com/) * Bootstrap v4.1.1 (https://getbootstrap.com/)
* Copyright 2011-2018 The Bootstrap Authors * Copyright 2011-2018 The Bootstrap Authors
* Copyright 2011-2018 Twitter, Inc. * Copyright 2011-2018 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
*/ */
@import "functions"; @import "functions";
@import "variables"; @import "variables";
@import "mixins"; @import "mixins";
@import "root"; @import "root";
@import "reboot"; @import "reboot";
@import "type"; @import "type";
@import "images"; @import "images";
@import "code"; @import "code";
@import "grid"; @import "grid";
@import "tables"; @import "tables";
@import "forms"; @import "forms";
@import "buttons"; @import "buttons";
@import "transitions"; @import "transitions";
@import "dropdown"; @import "dropdown";
@import "button-group"; @import "button-group";
@import "input-group"; @import "input-group";
@import "custom-forms"; @import "custom-forms";
@import "nav"; @import "nav";
@import "navbar"; @import "navbar";
@import "card"; @import "card";
@import "breadcrumb"; @import "breadcrumb";
@import "pagination"; @import "pagination";
@import "badge"; @import "badge";
@import "jumbotron"; @import "jumbotron";
@import "alert"; @import "alert";
@import "progress"; @import "progress";
@import "media"; @import "media";
@import "list-group"; @import "list-group";
@import "close"; @import "close";
@import "modal"; @import "modal";
@import "tooltip"; @import "tooltip";
@import "popover"; @import "popover";
@import "carousel"; @import "carousel";
@import "utilities"; @import "utilities";
@import "print"; @import "print";

View File

@@ -1,13 +1,13 @@
@mixin alert-variant($background, $border, $color) { @mixin alert-variant($background, $border, $color) {
color: $color; color: $color;
@include gradient-bg($background); @include gradient-bg($background);
border-color: $border; border-color: $border;
hr { hr {
border-top-color: darken($border, 5%); border-top-color: darken($border, 5%);
} }
.alert-link { .alert-link {
color: darken($color, 10%); color: darken($color, 10%);
} }
} }

View File

@@ -1,21 +1,21 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
// Contextual backgrounds // Contextual backgrounds
@mixin bg-variant($parent, $color) { @mixin bg-variant($parent, $color) {
#{$parent} { #{$parent} {
background-color: $color !important; background-color: $color !important;
} }
a#{$parent}, a#{$parent},
button#{$parent} { button#{$parent} {
@include hover-focus { @include hover-focus {
background-color: darken($color, 10%) !important; background-color: darken($color, 10%) !important;
} }
} }
} }
@mixin bg-gradient-variant($parent, $color) { @mixin bg-gradient-variant($parent, $color) {
#{$parent} { #{$parent} {
background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important; background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x !important;
} }
} }

View File

@@ -1,12 +1,12 @@
@mixin badge-variant($bg) { @mixin badge-variant($bg) {
color: color-yiq($bg); color: color-yiq($bg);
background-color: $bg; background-color: $bg;
&[href] { &[href] {
@include hover-focus { @include hover-focus {
color: color-yiq($bg); color: color-yiq($bg);
text-decoration: none; text-decoration: none;
background-color: darken($bg, 10%); background-color: darken($bg, 10%);
} }
} }
} }

View File

@@ -1,35 +1,35 @@
// Single side border-radius // Single side border-radius
@mixin border-radius($radius: $border-radius) { @mixin border-radius($radius: $border-radius) {
@if $enable-rounded { @if $enable-rounded {
border-radius: $radius; border-radius: $radius;
} }
} }
@mixin border-top-radius($radius) { @mixin border-top-radius($radius) {
@if $enable-rounded { @if $enable-rounded {
border-top-left-radius: $radius; border-top-left-radius: $radius;
border-top-right-radius: $radius; border-top-right-radius: $radius;
} }
} }
@mixin border-right-radius($radius) { @mixin border-right-radius($radius) {
@if $enable-rounded { @if $enable-rounded {
border-top-right-radius: $radius; border-top-right-radius: $radius;
border-bottom-right-radius: $radius; border-bottom-right-radius: $radius;
} }
} }
@mixin border-bottom-radius($radius) { @mixin border-bottom-radius($radius) {
@if $enable-rounded { @if $enable-rounded {
border-bottom-right-radius: $radius; border-bottom-right-radius: $radius;
border-bottom-left-radius: $radius; border-bottom-left-radius: $radius;
} }
} }
@mixin border-left-radius($radius) { @mixin border-left-radius($radius) {
@if $enable-rounded { @if $enable-rounded {
border-top-left-radius: $radius; border-top-left-radius: $radius;
border-bottom-left-radius: $radius; border-bottom-left-radius: $radius;
} }
} }

View File

@@ -1,5 +1,5 @@
@mixin box-shadow($shadow...) { @mixin box-shadow($shadow...) {
@if $enable-shadows { @if $enable-shadows {
box-shadow: $shadow; box-shadow: $shadow;
} }
} }

View File

@@ -1,123 +1,123 @@
// Breakpoint viewport sizes and media queries. // Breakpoint viewport sizes and media queries.
// //
// Breakpoints are defined as a map of (name: minimum width), order from small to large: // Breakpoints are defined as a map of (name: minimum width), order from small to large:
// //
// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px) // (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)
// //
// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default. // The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
// Name of the next breakpoint, or null for the last breakpoint. // Name of the next breakpoint, or null for the last breakpoint.
// //
// >> breakpoint-next(sm) // >> breakpoint-next(sm)
// md // md
// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) // >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// md // md
// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl)) // >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))
// md // md
@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) { @function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
$n: index($breakpoint-names, $name); $n: index($breakpoint-names, $name);
@return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null); @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
} }
// Minimum breakpoint width. Null for the smallest (first) breakpoint. // Minimum breakpoint width. Null for the smallest (first) breakpoint.
// //
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) // >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 576px // 576px
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) { @function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
$min: map-get($breakpoints, $name); $min: map-get($breakpoints, $name);
@return if($min != 0, $min, null); @return if($min != 0, $min, null);
} }
// Maximum breakpoint width. Null for the largest (last) breakpoint. // Maximum breakpoint width. Null for the largest (last) breakpoint.
// The maximum value is calculated as the minimum of the next one less 0.02px // The maximum value is calculated as the minimum of the next one less 0.02px
// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths. // to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.
// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max // See https://www.w3.org/TR/mediaqueries-4/#mq-min-max
// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari. // Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.
// See https://bugs.webkit.org/show_bug.cgi?id=178261 // See https://bugs.webkit.org/show_bug.cgi?id=178261
// //
// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) // >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 767.98px // 767.98px
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) { @function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
$next: breakpoint-next($name, $breakpoints); $next: breakpoint-next($name, $breakpoints);
@return if($next, breakpoint-min($next, $breakpoints) - .02px, null); @return if($next, breakpoint-min($next, $breakpoints) - .02px, null);
} }
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront. // Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront.
// Useful for making responsive utilities. // Useful for making responsive utilities.
// //
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) // >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "" (Returns a blank string) // "" (Returns a blank string)
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)) // >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "-sm" // "-sm"
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) { @function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}"); @return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
} }
// Media of at least the minimum breakpoint width. No query for the smallest breakpoint. // Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
// Makes the @content apply to the given breakpoint and wider. // Makes the @content apply to the given breakpoint and wider.
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) { @mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints); $min: breakpoint-min($name, $breakpoints);
@if $min { @if $min {
@media (min-width: $min) { @media (min-width: $min) {
@content; @content;
} }
} @else { } @else {
@content; @content;
} }
} }
// Media of at most the maximum breakpoint width. No query for the largest breakpoint. // Media of at most the maximum breakpoint width. No query for the largest breakpoint.
// Makes the @content apply to the given breakpoint and narrower. // Makes the @content apply to the given breakpoint and narrower.
@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) { @mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
$max: breakpoint-max($name, $breakpoints); $max: breakpoint-max($name, $breakpoints);
@if $max { @if $max {
@media (max-width: $max) { @media (max-width: $max) {
@content; @content;
} }
} @else { } @else {
@content; @content;
} }
} }
// Media that spans multiple breakpoint widths. // Media that spans multiple breakpoint widths.
// Makes the @content apply between the min and max breakpoints // Makes the @content apply between the min and max breakpoints
@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) { @mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($lower, $breakpoints); $min: breakpoint-min($lower, $breakpoints);
$max: breakpoint-max($upper, $breakpoints); $max: breakpoint-max($upper, $breakpoints);
@if $min != null and $max != null { @if $min != null and $max != null {
@media (min-width: $min) and (max-width: $max) { @media (min-width: $min) and (max-width: $max) {
@content; @content;
} }
} @else if $max == null { } @else if $max == null {
@include media-breakpoint-up($lower, $breakpoints) { @include media-breakpoint-up($lower, $breakpoints) {
@content; @content;
} }
} @else if $min == null { } @else if $min == null {
@include media-breakpoint-down($upper, $breakpoints) { @include media-breakpoint-down($upper, $breakpoints) {
@content; @content;
} }
} }
} }
// Media between the breakpoint's minimum and maximum widths. // Media between the breakpoint's minimum and maximum widths.
// No minimum for the smallest breakpoint, and no maximum for the largest one. // No minimum for the smallest breakpoint, and no maximum for the largest one.
// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower. // Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) { @mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints); $min: breakpoint-min($name, $breakpoints);
$max: breakpoint-max($name, $breakpoints); $max: breakpoint-max($name, $breakpoints);
@if $min != null and $max != null { @if $min != null and $max != null {
@media (min-width: $min) and (max-width: $max) { @media (min-width: $min) and (max-width: $max) {
@content; @content;
} }
} @else if $max == null { } @else if $max == null {
@include media-breakpoint-up($name, $breakpoints) { @include media-breakpoint-up($name, $breakpoints) {
@content; @content;
} }
} @else if $min == null { } @else if $min == null {
@include media-breakpoint-down($name, $breakpoints) { @include media-breakpoint-down($name, $breakpoints) {
@content; @content;
} }
} }
} }

View File

@@ -1,109 +1,109 @@
// Button variants // Button variants
// //
// Easily pump out default styles, as well as :hover, :focus, :active, // Easily pump out default styles, as well as :hover, :focus, :active,
// and disabled options for all buttons // and disabled options for all buttons
@mixin button-variant($background, $border, $hover-background: darken($background, 7.5%), $hover-border: darken($border, 10%), $active-background: darken($background, 10%), $active-border: darken($border, 12.5%)) { @mixin button-variant($background, $border, $hover-background: darken($background, 7.5%), $hover-border: darken($border, 10%), $active-background: darken($background, 10%), $active-border: darken($border, 12.5%)) {
color: color-yiq($background); color: color-yiq($background);
@include gradient-bg($background); @include gradient-bg($background);
border-color: $border; border-color: $border;
@include box-shadow($btn-box-shadow); @include box-shadow($btn-box-shadow);
@include hover { @include hover {
color: color-yiq($hover-background); color: color-yiq($hover-background);
@include gradient-bg($hover-background); @include gradient-bg($hover-background);
border-color: $hover-border; border-color: $hover-border;
} }
&:focus, &:focus,
&.focus { &.focus {
// Avoid using mixin so we can pass custom focus shadow properly // Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows { @if $enable-shadows {
box-shadow: $btn-box-shadow, 0 0 0 $btn-focus-width rgba($border, .5); box-shadow: $btn-box-shadow, 0 0 0 $btn-focus-width rgba($border, .5);
} @else { } @else {
box-shadow: 0 0 0 $btn-focus-width rgba($border, .5); box-shadow: 0 0 0 $btn-focus-width rgba($border, .5);
} }
} }
// Disabled comes first so active can properly restyle // Disabled comes first so active can properly restyle
&.disabled, &.disabled,
&:disabled { &:disabled {
color: color-yiq($background); color: color-yiq($background);
background-color: $background; background-color: $background;
border-color: $border; border-color: $border;
} }
&:not(:disabled):not(.disabled):active, &:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled).active, &:not(:disabled):not(.disabled).active,
.show > &.dropdown-toggle { .show > &.dropdown-toggle {
color: color-yiq($active-background); color: color-yiq($active-background);
background-color: $active-background; background-color: $active-background;
@if $enable-gradients { @if $enable-gradients {
background-image: none; // Remove the gradient for the pressed/active state background-image: none; // Remove the gradient for the pressed/active state
} }
border-color: $active-border; border-color: $active-border;
&:focus { &:focus {
// Avoid using mixin so we can pass custom focus shadow properly // Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows { @if $enable-shadows {
box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($border, .5); box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($border, .5);
} @else { } @else {
box-shadow: 0 0 0 $btn-focus-width rgba($border, .5); box-shadow: 0 0 0 $btn-focus-width rgba($border, .5);
} }
} }
} }
} }
@mixin button-outline-variant($color, $color-hover: color-yiq($color), $active-background: $color, $active-border: $color) { @mixin button-outline-variant($color, $color-hover: color-yiq($color), $active-background: $color, $active-border: $color) {
color: $color; color: $color;
background-color: transparent; background-color: transparent;
background-image: none; background-image: none;
border-color: $color; border-color: $color;
&:hover { &:hover {
color: $color-hover; color: $color-hover;
background-color: $active-background; background-color: $active-background;
border-color: $active-border; border-color: $active-border;
} }
&:focus, &:focus,
&.focus { &.focus {
box-shadow: 0 0 0 $btn-focus-width rgba($color, .5); box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);
} }
&.disabled, &.disabled,
&:disabled { &:disabled {
color: $color; color: $color;
background-color: transparent; background-color: transparent;
} }
&:not(:disabled):not(.disabled):active, &:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled).active, &:not(:disabled):not(.disabled).active,
.show > &.dropdown-toggle { .show > &.dropdown-toggle {
color: color-yiq($active-background); color: color-yiq($active-background);
background-color: $active-background; background-color: $active-background;
border-color: $active-border; border-color: $active-border;
&:focus { &:focus {
// Avoid using mixin so we can pass custom focus shadow properly // Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows and $btn-active-box-shadow != none { @if $enable-shadows and $btn-active-box-shadow != none {
box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($color, .5); box-shadow: $btn-active-box-shadow, 0 0 0 $btn-focus-width rgba($color, .5);
} @else { } @else {
box-shadow: 0 0 0 $btn-focus-width rgba($color, .5); box-shadow: 0 0 0 $btn-focus-width rgba($color, .5);
} }
} }
} }
} }
// Button sizes // Button sizes
@mixin button-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) { @mixin button-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {
padding: $padding-y $padding-x; padding: $padding-y $padding-x;
font-size: $font-size; font-size: $font-size;
line-height: $line-height; line-height: $line-height;
// Manually declare to provide an override to the browser default // Manually declare to provide an override to the browser default
@if $enable-rounded { @if $enable-rounded {
border-radius: $border-radius; border-radius: $border-radius;
} @else { } @else {
border-radius: 0; border-radius: 0;
} }
} }

View File

@@ -1,66 +1,66 @@
@mixin caret-down { @mixin caret-down {
border-top: $caret-width solid; border-top: $caret-width solid;
border-right: $caret-width solid transparent; border-right: $caret-width solid transparent;
border-bottom: 0; border-bottom: 0;
border-left: $caret-width solid transparent; border-left: $caret-width solid transparent;
} }
@mixin caret-up { @mixin caret-up {
border-top: 0; border-top: 0;
border-right: $caret-width solid transparent; border-right: $caret-width solid transparent;
border-bottom: $caret-width solid; border-bottom: $caret-width solid;
border-left: $caret-width solid transparent; border-left: $caret-width solid transparent;
} }
@mixin caret-right { @mixin caret-right {
border-top: $caret-width solid transparent; border-top: $caret-width solid transparent;
border-right: 0; border-right: 0;
border-bottom: $caret-width solid transparent; border-bottom: $caret-width solid transparent;
border-left: $caret-width solid; border-left: $caret-width solid;
} }
@mixin caret-left { @mixin caret-left {
border-top: $caret-width solid transparent; border-top: $caret-width solid transparent;
border-right: $caret-width solid; border-right: $caret-width solid;
border-bottom: $caret-width solid transparent; border-bottom: $caret-width solid transparent;
} }
@mixin caret($direction: down) { @mixin caret($direction: down) {
@if $enable-caret { @if $enable-caret {
&::after { &::after {
display: inline-block; display: inline-block;
width: 0; width: 0;
height: 0; height: 0;
margin-left: $caret-width * .85; margin-left: $caret-width * .85;
vertical-align: $caret-width * .85; vertical-align: $caret-width * .85;
content: ""; content: "";
@if $direction == down { @if $direction == down {
@include caret-down; @include caret-down;
} @else if $direction == up { } @else if $direction == up {
@include caret-up; @include caret-up;
} @else if $direction == right { } @else if $direction == right {
@include caret-right; @include caret-right;
} }
} }
@if $direction == left { @if $direction == left {
&::after { &::after {
display: none; display: none;
} }
&::before { &::before {
display: inline-block; display: inline-block;
width: 0; width: 0;
height: 0; height: 0;
margin-right: $caret-width * .85; margin-right: $caret-width * .85;
vertical-align: $caret-width * .85; vertical-align: $caret-width * .85;
content: ""; content: "";
@include caret-left; @include caret-left;
} }
} }
&:empty::after { &:empty::after {
margin-left: 0; margin-left: 0;
} }
} }
} }

View File

@@ -1,7 +1,7 @@
@mixin clearfix() { @mixin clearfix() {
&::after { &::after {
display: block; display: block;
clear: both; clear: both;
content: ""; content: "";
} }
} }

View File

@@ -1,11 +1,11 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
@mixin float-left { @mixin float-left {
float: left !important; float: left !important;
} }
@mixin float-right { @mixin float-right {
float: right !important; float: right !important;
} }
@mixin float-none { @mixin float-none {
float: none !important; float: none !important;
} }

View File

@@ -1,147 +1,147 @@
// Form control focus state // Form control focus state
// //
// Generate a customized focus state and for any input with the specified color, // Generate a customized focus state and for any input with the specified color,
// which defaults to the `$input-focus-border-color` variable. // which defaults to the `$input-focus-border-color` variable.
// //
// We highly encourage you to not customize the default value, but instead use // We highly encourage you to not customize the default value, but instead use
// this to tweak colors on an as-needed basis. This aesthetic change is based on // this to tweak colors on an as-needed basis. This aesthetic change is based on
// WebKit's default styles, but applicable to a wider range of browsers. Its // WebKit's default styles, but applicable to a wider range of browsers. Its
// usability and accessibility should be taken into account with any change. // usability and accessibility should be taken into account with any change.
// //
// Example usage: change the default blue border and shadow to white for better // Example usage: change the default blue border and shadow to white for better
// contrast against a dark gray background. // contrast against a dark gray background.
@mixin form-control-focus() { @mixin form-control-focus() {
&:focus { &:focus {
color: $input-focus-color; color: $input-focus-color;
background-color: $input-focus-bg; background-color: $input-focus-bg;
border-color: $input-focus-border-color; border-color: $input-focus-border-color;
outline: 0; outline: 0;
// Avoid using mixin so we can pass custom focus shadow properly // Avoid using mixin so we can pass custom focus shadow properly
@if $enable-shadows { @if $enable-shadows {
box-shadow: $input-box-shadow, $input-focus-box-shadow; box-shadow: $input-box-shadow, $input-focus-box-shadow;
} @else { } @else {
box-shadow: $input-focus-box-shadow; box-shadow: $input-focus-box-shadow;
} }
} }
} }
@mixin form-validation-state($state, $color) { @mixin form-validation-state($state, $color) {
.#{$state}-feedback { .#{$state}-feedback {
display: none; display: none;
width: 100%; width: 100%;
margin-top: $form-feedback-margin-top; margin-top: $form-feedback-margin-top;
font-size: $form-feedback-font-size; font-size: $form-feedback-font-size;
color: $color; color: $color;
} }
.#{$state}-tooltip { .#{$state}-tooltip {
position: absolute; position: absolute;
top: 100%; top: 100%;
z-index: 5; z-index: 5;
display: none; display: none;
max-width: 100%; // Contain to parent when possible max-width: 100%; // Contain to parent when possible
padding: .5rem; padding: .5rem;
margin-top: .1rem; margin-top: .1rem;
font-size: .875rem; font-size: .875rem;
line-height: 1; line-height: 1;
color: $white; color: $white;
background-color: rgba($color, .8); background-color: rgba($color, .8);
border-radius: .2rem; border-radius: .2rem;
} }
.form-control, .form-control,
.custom-select { .custom-select {
.was-validated &:#{$state}, .was-validated &:#{$state},
&.is-#{$state} { &.is-#{$state} {
border-color: $color; border-color: $color;
&:focus { &:focus {
border-color: $color; border-color: $color;
box-shadow: 0 0 0 $input-focus-width rgba($color, .25); box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
} }
~ .#{$state}-feedback, ~ .#{$state}-feedback,
~ .#{$state}-tooltip { ~ .#{$state}-tooltip {
display: block; display: block;
} }
} }
} }
.form-control-file { .form-control-file {
.was-validated &:#{$state}, .was-validated &:#{$state},
&.is-#{$state} { &.is-#{$state} {
~ .#{$state}-feedback, ~ .#{$state}-feedback,
~ .#{$state}-tooltip { ~ .#{$state}-tooltip {
display: block; display: block;
} }
} }
} }
.form-check-input { .form-check-input {
.was-validated &:#{$state}, .was-validated &:#{$state},
&.is-#{$state} { &.is-#{$state} {
~ .form-check-label { ~ .form-check-label {
color: $color; color: $color;
} }
~ .#{$state}-feedback, ~ .#{$state}-feedback,
~ .#{$state}-tooltip { ~ .#{$state}-tooltip {
display: block; display: block;
} }
} }
} }
.custom-control-input { .custom-control-input {
.was-validated &:#{$state}, .was-validated &:#{$state},
&.is-#{$state} { &.is-#{$state} {
~ .custom-control-label { ~ .custom-control-label {
color: $color; color: $color;
&::before { &::before {
background-color: lighten($color, 25%); background-color: lighten($color, 25%);
} }
} }
~ .#{$state}-feedback, ~ .#{$state}-feedback,
~ .#{$state}-tooltip { ~ .#{$state}-tooltip {
display: block; display: block;
} }
&:checked { &:checked {
~ .custom-control-label::before { ~ .custom-control-label::before {
@include gradient-bg(lighten($color, 10%)); @include gradient-bg(lighten($color, 10%));
} }
} }
&:focus { &:focus {
~ .custom-control-label::before { ~ .custom-control-label::before {
box-shadow: 0 0 0 1px $body-bg, 0 0 0 $input-focus-width rgba($color, .25); box-shadow: 0 0 0 1px $body-bg, 0 0 0 $input-focus-width rgba($color, .25);
} }
} }
} }
} }
// custom file // custom file
.custom-file-input { .custom-file-input {
.was-validated &:#{$state}, .was-validated &:#{$state},
&.is-#{$state} { &.is-#{$state} {
~ .custom-file-label { ~ .custom-file-label {
border-color: $color; border-color: $color;
&::before { border-color: inherit; } &::before { border-color: inherit; }
} }
~ .#{$state}-feedback, ~ .#{$state}-feedback,
~ .#{$state}-tooltip { ~ .#{$state}-tooltip {
display: block; display: block;
} }
&:focus { &:focus {
~ .custom-file-label { ~ .custom-file-label {
box-shadow: 0 0 0 $input-focus-width rgba($color, .25); box-shadow: 0 0 0 $input-focus-width rgba($color, .25);
} }
} }
} }
} }
} }

View File

@@ -1,45 +1,45 @@
// Gradients // Gradients
@mixin gradient-bg($color) { @mixin gradient-bg($color) {
@if $enable-gradients { @if $enable-gradients {
background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x; background: $color linear-gradient(180deg, mix($body-bg, $color, 15%), $color) repeat-x;
} @else { } @else {
background-color: $color; background-color: $color;
} }
} }
// Horizontal gradient, from left to right // Horizontal gradient, from left to right
// //
// Creates two color stops, start and end, by specifying a color and position for each color stop. // Creates two color stops, start and end, by specifying a color and position for each color stop.
@mixin gradient-x($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) { @mixin gradient-x($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {
background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent); background-image: linear-gradient(to right, $start-color $start-percent, $end-color $end-percent);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
// Vertical gradient, from top to bottom // Vertical gradient, from top to bottom
// //
// Creates two color stops, start and end, by specifying a color and position for each color stop. // Creates two color stops, start and end, by specifying a color and position for each color stop.
@mixin gradient-y($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) { @mixin gradient-y($start-color: $gray-700, $end-color: $gray-800, $start-percent: 0%, $end-percent: 100%) {
background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent); background-image: linear-gradient(to bottom, $start-color $start-percent, $end-color $end-percent);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
@mixin gradient-directional($start-color: $gray-700, $end-color: $gray-800, $deg: 45deg) { @mixin gradient-directional($start-color: $gray-700, $end-color: $gray-800, $deg: 45deg) {
background-image: linear-gradient($deg, $start-color, $end-color); background-image: linear-gradient($deg, $start-color, $end-color);
background-repeat: repeat-x; background-repeat: repeat-x;
} }
@mixin gradient-x-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) { @mixin gradient-x-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) {
background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color); background-image: linear-gradient(to right, $start-color, $mid-color $color-stop, $end-color);
background-repeat: no-repeat; background-repeat: no-repeat;
} }
@mixin gradient-y-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) { @mixin gradient-y-three-colors($start-color: $blue, $mid-color: $purple, $color-stop: 50%, $end-color: $red) {
background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color); background-image: linear-gradient($start-color, $mid-color $color-stop, $end-color);
background-repeat: no-repeat; background-repeat: no-repeat;
} }
@mixin gradient-radial($inner-color: $gray-700, $outer-color: $gray-800) { @mixin gradient-radial($inner-color: $gray-700, $outer-color: $gray-800) {
background-image: radial-gradient(circle, $inner-color, $outer-color); background-image: radial-gradient(circle, $inner-color, $outer-color);
background-repeat: no-repeat; background-repeat: no-repeat;
} }
@mixin gradient-striped($color: rgba($white, .15), $angle: 45deg) { @mixin gradient-striped($color: rgba($white, .15), $angle: 45deg) {
background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent); background-image: linear-gradient($angle, $color 25%, transparent 25%, transparent 50%, $color 50%, $color 75%, transparent 75%, transparent);
} }

View File

@@ -1,67 +1,67 @@
// Framework grid generation // Framework grid generation
// //
// Used only by Bootstrap to generate the correct number of grid classes given // Used only by Bootstrap to generate the correct number of grid classes given
// any value of `$grid-columns`. // any value of `$grid-columns`.
@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) { @mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {
// Common properties for all breakpoints // Common properties for all breakpoints
%grid-column { %grid-column {
position: relative; position: relative;
width: 100%; width: 100%;
min-height: 1px; // Prevent columns from collapsing when empty min-height: 1px; // Prevent columns from collapsing when empty
padding-right: ($gutter / 2); padding-right: ($gutter / 2);
padding-left: ($gutter / 2); padding-left: ($gutter / 2);
} }
@each $breakpoint in map-keys($breakpoints) { @each $breakpoint in map-keys($breakpoints) {
$infix: breakpoint-infix($breakpoint, $breakpoints); $infix: breakpoint-infix($breakpoint, $breakpoints);
// Allow columns to stretch full width below their breakpoints // Allow columns to stretch full width below their breakpoints
@for $i from 1 through $columns { @for $i from 1 through $columns {
.col#{$infix}-#{$i} { .col#{$infix}-#{$i} {
@extend %grid-column; @extend %grid-column;
} }
} }
.col#{$infix}, .col#{$infix},
.col#{$infix}-auto { .col#{$infix}-auto {
@extend %grid-column; @extend %grid-column;
} }
@include media-breakpoint-up($breakpoint, $breakpoints) { @include media-breakpoint-up($breakpoint, $breakpoints) {
// Provide basic `.col-{bp}` classes for equal-width flexbox columns // Provide basic `.col-{bp}` classes for equal-width flexbox columns
.col#{$infix} { .col#{$infix} {
flex-basis: 0; flex-basis: 0;
flex-grow: 1; flex-grow: 1;
max-width: 100%; max-width: 100%;
} }
.col#{$infix}-auto { .col#{$infix}-auto {
flex: 0 0 auto; flex: 0 0 auto;
width: auto; width: auto;
max-width: none; // Reset earlier grid tiers max-width: none; // Reset earlier grid tiers
} }
@for $i from 1 through $columns { @for $i from 1 through $columns {
.col#{$infix}-#{$i} { .col#{$infix}-#{$i} {
@include make-col($i, $columns); @include make-col($i, $columns);
} }
} }
.order#{$infix}-first { order: -1; } .order#{$infix}-first { order: -1; }
.order#{$infix}-last { order: $columns + 1; } .order#{$infix}-last { order: $columns + 1; }
@for $i from 0 through $columns { @for $i from 0 through $columns {
.order#{$infix}-#{$i} { order: $i; } .order#{$infix}-#{$i} { order: $i; }
} }
// `$columns - 1` because offsetting by the width of an entire row isn't possible // `$columns - 1` because offsetting by the width of an entire row isn't possible
@for $i from 0 through ($columns - 1) { @for $i from 0 through ($columns - 1) {
@if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0 @if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0
.offset#{$infix}-#{$i} { .offset#{$infix}-#{$i} {
@include make-col-offset($i, $columns); @include make-col-offset($i, $columns);
} }
} }
} }
} }
} }
} }

View File

@@ -1,52 +1,52 @@
/// Grid system /// Grid system
// //
// Generate semantic grid columns with these mixins. // Generate semantic grid columns with these mixins.
@mixin make-container() { @mixin make-container() {
width: 100%; width: 100%;
padding-right: ($grid-gutter-width / 2); padding-right: ($grid-gutter-width / 2);
padding-left: ($grid-gutter-width / 2); padding-left: ($grid-gutter-width / 2);
margin-right: auto; margin-right: auto;
margin-left: auto; margin-left: auto;
} }
// For each breakpoint, define the maximum width of the container in a media query // For each breakpoint, define the maximum width of the container in a media query
@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) { @mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {
@each $breakpoint, $container-max-width in $max-widths { @each $breakpoint, $container-max-width in $max-widths {
@include media-breakpoint-up($breakpoint, $breakpoints) { @include media-breakpoint-up($breakpoint, $breakpoints) {
max-width: $container-max-width; max-width: $container-max-width;
} }
} }
} }
@mixin make-row() { @mixin make-row() {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin-right: ($grid-gutter-width / -2); margin-right: ($grid-gutter-width / -2);
margin-left: ($grid-gutter-width / -2); margin-left: ($grid-gutter-width / -2);
} }
@mixin make-col-ready() { @mixin make-col-ready() {
position: relative; position: relative;
// Prevent columns from becoming too narrow when at smaller grid tiers by // Prevent columns from becoming too narrow when at smaller grid tiers by
// always setting `width: 100%;`. This works because we use `flex` values // always setting `width: 100%;`. This works because we use `flex` values
// later on to override this initial width. // later on to override this initial width.
width: 100%; width: 100%;
min-height: 1px; // Prevent collapsing min-height: 1px; // Prevent collapsing
padding-right: ($grid-gutter-width / 2); padding-right: ($grid-gutter-width / 2);
padding-left: ($grid-gutter-width / 2); padding-left: ($grid-gutter-width / 2);
} }
@mixin make-col($size, $columns: $grid-columns) { @mixin make-col($size, $columns: $grid-columns) {
flex: 0 0 percentage($size / $columns); flex: 0 0 percentage($size / $columns);
// Add a `max-width` to ensure content within each column does not blow out // Add a `max-width` to ensure content within each column does not blow out
// the width of the column. Applies to IE10+ and Firefox. Chrome and Safari // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari
// do not appear to require this. // do not appear to require this.
max-width: percentage($size / $columns); max-width: percentage($size / $columns);
} }
@mixin make-col-offset($size, $columns: $grid-columns) { @mixin make-col-offset($size, $columns: $grid-columns) {
$num: $size / $columns; $num: $size / $columns;
margin-left: if($num == 0, 0, percentage($num)); margin-left: if($num == 0, 0, percentage($num));
} }

View File

@@ -1,37 +1,37 @@
// Hover mixin and `$enable-hover-media-query` are deprecated. // Hover mixin and `$enable-hover-media-query` are deprecated.
// //
// Origally added during our alphas and maintained during betas, this mixin was // Origally added during our alphas and maintained during betas, this mixin was
// designed to prevent `:hover` stickiness on iOS-an issue where hover styles // designed to prevent `:hover` stickiness on iOS-an issue where hover styles
// would persist after initial touch. // would persist after initial touch.
// //
// For backward compatibility, we've kept these mixins and updated them to // For backward compatibility, we've kept these mixins and updated them to
// always return their regular pseudo-classes instead of a shimmed media query. // always return their regular pseudo-classes instead of a shimmed media query.
// //
// Issue: https://github.com/twbs/bootstrap/issues/25195 // Issue: https://github.com/twbs/bootstrap/issues/25195
@mixin hover { @mixin hover {
&:hover { @content; } &:hover { @content; }
} }
@mixin hover-focus { @mixin hover-focus {
&:hover, &:hover,
&:focus { &:focus {
@content; @content;
} }
} }
@mixin plain-hover-focus { @mixin plain-hover-focus {
&, &,
&:hover, &:hover,
&:focus { &:focus {
@content; @content;
} }
} }
@mixin hover-focus-active { @mixin hover-focus-active {
&:hover, &:hover,
&:focus, &:focus,
&:active { &:active {
@content; @content;
} }
} }

View File

@@ -1,36 +1,36 @@
// Image Mixins // Image Mixins
// - Responsive image // - Responsive image
// - Retina image // - Retina image
// Responsive image // Responsive image
// //
// Keep images from scaling beyond the width of their parents. // Keep images from scaling beyond the width of their parents.
@mixin img-fluid { @mixin img-fluid {
// Part 1: Set a maximum relative to the parent // Part 1: Set a maximum relative to the parent
max-width: 100%; max-width: 100%;
// Part 2: Override the height to auto, otherwise images will be stretched // Part 2: Override the height to auto, otherwise images will be stretched
// when setting a width and height attribute on the img element. // when setting a width and height attribute on the img element.
height: auto; height: auto;
} }
// Retina image // Retina image
// //
// Short retina mixin for setting background-image and -size. // Short retina mixin for setting background-image and -size.
// stylelint-disable indentation, media-query-list-comma-newline-after // stylelint-disable indentation, media-query-list-comma-newline-after
@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) { @mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {
background-image: url($file-1x); background-image: url($file-1x);
// Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio, // Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio,
// but doesn't convert dppx=>dpi. // but doesn't convert dppx=>dpi.
// There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard. // There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard.
// Compatibility info: https://caniuse.com/#feat=css-media-resolution // Compatibility info: https://caniuse.com/#feat=css-media-resolution
@media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx @media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx
only screen and (min-resolution: 2dppx) { // Standardized only screen and (min-resolution: 2dppx) { // Standardized
background-image: url($file-2x); background-image: url($file-2x);
background-size: $width-1x $height-1x; background-size: $width-1x $height-1x;
} }
} }

View File

@@ -1,21 +1,21 @@
// List Groups // List Groups
@mixin list-group-item-variant($state, $background, $color) { @mixin list-group-item-variant($state, $background, $color) {
.list-group-item-#{$state} { .list-group-item-#{$state} {
color: $color; color: $color;
background-color: $background; background-color: $background;
&.list-group-item-action { &.list-group-item-action {
@include hover-focus { @include hover-focus {
color: $color; color: $color;
background-color: darken($background, 5%); background-color: darken($background, 5%);
} }
&.active { &.active {
color: $white; color: $white;
background-color: $color; background-color: $color;
border-color: $color; border-color: $color;
} }
} }
} }
} }

View File

@@ -1,7 +1,7 @@
// Lists // Lists
// Unstyled keeps list items block level, just removes default browser padding and list-style // Unstyled keeps list items block level, just removes default browser padding and list-style
@mixin list-unstyled { @mixin list-unstyled {
padding-left: 0; padding-left: 0;
list-style: none; list-style: none;
} }

View File

@@ -1,10 +1,10 @@
// Horizontal dividers // Horizontal dividers
// //
// Dividers (basically an hr) within dropdowns and nav lists // Dividers (basically an hr) within dropdowns and nav lists
@mixin nav-divider($color: $nav-divider-color, $margin-y: $nav-divider-margin-y) { @mixin nav-divider($color: $nav-divider-color, $margin-y: $nav-divider-margin-y) {
height: 0; height: 0;
margin: $margin-y 0; margin: $margin-y 0;
overflow: hidden; overflow: hidden;
border-top: 1px solid $color; border-top: 1px solid $color;
} }

View File

@@ -1,22 +1,22 @@
// Pagination // Pagination
@mixin pagination-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) { @mixin pagination-size($padding-y, $padding-x, $font-size, $line-height, $border-radius) {
.page-link { .page-link {
padding: $padding-y $padding-x; padding: $padding-y $padding-x;
font-size: $font-size; font-size: $font-size;
line-height: $line-height; line-height: $line-height;
} }
.page-item { .page-item {
&:first-child { &:first-child {
.page-link { .page-link {
@include border-left-radius($border-radius); @include border-left-radius($border-radius);
} }
} }
&:last-child { &:last-child {
.page-link { .page-link {
@include border-right-radius($border-radius); @include border-right-radius($border-radius);
} }
} }
} }
} }

View File

@@ -1,17 +1,17 @@
@mixin reset-text { @mixin reset-text {
font-family: $font-family-base; font-family: $font-family-base;
// We deliberately do NOT reset font-size or word-wrap. // We deliberately do NOT reset font-size or word-wrap.
font-style: normal; font-style: normal;
font-weight: $font-weight-normal; font-weight: $font-weight-normal;
line-height: $line-height-base; line-height: $line-height-base;
text-align: left; // Fallback for where `start` is not supported text-align: left; // Fallback for where `start` is not supported
text-align: start; // stylelint-disable-line declaration-block-no-duplicate-properties text-align: start; // stylelint-disable-line declaration-block-no-duplicate-properties
text-decoration: none; text-decoration: none;
text-shadow: none; text-shadow: none;
text-transform: none; text-transform: none;
letter-spacing: normal; letter-spacing: normal;
word-break: normal; word-break: normal;
word-spacing: normal; word-spacing: normal;
white-space: normal; white-space: normal;
line-break: auto; line-break: auto;
} }

View File

@@ -1,6 +1,6 @@
// Resize anything // Resize anything
@mixin resizable($direction) { @mixin resizable($direction) {
overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible` overflow: auto; // Per CSS3 UI, `resize` only applies when `overflow` isn't `visible`
resize: $direction; // Options: horizontal, vertical, both resize: $direction; // Options: horizontal, vertical, both
} }

View File

@@ -1,33 +1,33 @@
// Only display content to screen readers // Only display content to screen readers
// //
// See: https://a11yproject.com/posts/how-to-hide-content/ // See: https://a11yproject.com/posts/how-to-hide-content/
// See: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/ // See: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/
@mixin sr-only { @mixin sr-only {
position: absolute; position: absolute;
width: 1px; width: 1px;
height: 1px; height: 1px;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden;
clip: rect(0, 0, 0, 0); clip: rect(0, 0, 0, 0);
white-space: nowrap; white-space: nowrap;
border: 0; border: 0;
} }
// Use in conjunction with .sr-only to only display content when it's focused. // Use in conjunction with .sr-only to only display content when it's focused.
// //
// Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 // Useful for "Skip to main content" links; see https://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1
// //
// Credit: HTML5 Boilerplate // Credit: HTML5 Boilerplate
@mixin sr-only-focusable { @mixin sr-only-focusable {
&:active, &:active,
&:focus { &:focus {
position: static; position: static;
width: auto; width: auto;
height: auto; height: auto;
overflow: visible; overflow: visible;
clip: auto; clip: auto;
white-space: normal; white-space: normal;
} }
} }

View File

@@ -1,6 +1,6 @@
// Sizing shortcuts // Sizing shortcuts
@mixin size($width, $height: $width) { @mixin size($width, $height: $width) {
width: $width; width: $width;
height: $height; height: $height;
} }

View File

@@ -1,30 +1,30 @@
// Tables // Tables
@mixin table-row-variant($state, $background) { @mixin table-row-variant($state, $background) {
// Exact selectors below required to override `.table-striped` and prevent // Exact selectors below required to override `.table-striped` and prevent
// inheritance to nested tables. // inheritance to nested tables.
.table-#{$state} { .table-#{$state} {
&, &,
> th, > th,
> td { > td {
background-color: $background; background-color: $background;
} }
} }
// Hover states for `.table-hover` // Hover states for `.table-hover`
// Note: this is not available for cells or rows within `thead` or `tfoot`. // Note: this is not available for cells or rows within `thead` or `tfoot`.
.table-hover { .table-hover {
$hover-background: darken($background, 5%); $hover-background: darken($background, 5%);
.table-#{$state} { .table-#{$state} {
@include hover { @include hover {
background-color: $hover-background; background-color: $hover-background;
> td, > td,
> th { > th {
background-color: $hover-background; background-color: $hover-background;
} }
} }
} }
} }
} }

View File

@@ -1,14 +1,14 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
// Typography // Typography
@mixin text-emphasis-variant($parent, $color) { @mixin text-emphasis-variant($parent, $color) {
#{$parent} { #{$parent} {
color: $color !important; color: $color !important;
} }
a#{$parent} { a#{$parent} {
@include hover-focus { @include hover-focus {
color: darken($color, 10%) !important; color: darken($color, 10%) !important;
} }
} }
} }

View File

@@ -1,13 +1,13 @@
// CSS image replacement // CSS image replacement
@mixin text-hide($ignore-warning: false) { @mixin text-hide($ignore-warning: false) {
// stylelint-disable-next-line font-family-no-missing-generic-family-keyword // stylelint-disable-next-line font-family-no-missing-generic-family-keyword
font: 0/0 a; font: 0/0 a;
color: transparent; color: transparent;
text-shadow: none; text-shadow: none;
background-color: transparent; background-color: transparent;
border: 0; border: 0;
@if ($ignore-warning != true) { @if ($ignore-warning != true) {
@warn "The `text-hide()` mixin has been deprecated as of v4.1.0. It will be removed entirely in v5."; @warn "The `text-hide()` mixin has been deprecated as of v4.1.0. It will be removed entirely in v5.";
} }
} }

View File

@@ -1,8 +1,8 @@
// Text truncate // Text truncate
// Requires inline-block or block for proper styling // Requires inline-block or block for proper styling
@mixin text-truncate() { @mixin text-truncate() {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }

View File

@@ -1,13 +1,13 @@
@mixin transition($transition...) { @mixin transition($transition...) {
@if $enable-transitions { @if $enable-transitions {
@if length($transition) == 0 { @if length($transition) == 0 {
transition: $transition-base; transition: $transition-base;
} @else { } @else {
transition: $transition; transition: $transition;
} }
} }
@media screen and (prefers-reduced-motion: reduce) { @media screen and (prefers-reduced-motion: reduce) {
transition: none; transition: none;
} }
} }

View File

@@ -1,7 +1,7 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
// Visibility // Visibility
@mixin invisible($visibility) { @mixin invisible($visibility) {
visibility: $visibility !important; visibility: $visibility !important;
} }

View File

@@ -1,8 +1,8 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
.align-baseline { vertical-align: baseline !important; } // Browser default .align-baseline { vertical-align: baseline !important; } // Browser default
.align-top { vertical-align: top !important; } .align-top { vertical-align: top !important; }
.align-middle { vertical-align: middle !important; } .align-middle { vertical-align: middle !important; }
.align-bottom { vertical-align: bottom !important; } .align-bottom { vertical-align: bottom !important; }
.align-text-bottom { vertical-align: text-bottom !important; } .align-text-bottom { vertical-align: text-bottom !important; }
.align-text-top { vertical-align: text-top !important; } .align-text-top { vertical-align: text-top !important; }

View File

@@ -1,19 +1,19 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
@include bg-variant(".bg-#{$color}", $value); @include bg-variant(".bg-#{$color}", $value);
} }
@if $enable-gradients { @if $enable-gradients {
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
@include bg-gradient-variant(".bg-gradient-#{$color}", $value); @include bg-gradient-variant(".bg-gradient-#{$color}", $value);
} }
} }
.bg-white { .bg-white {
background-color: $white !important; background-color: $white !important;
} }
.bg-transparent { .bg-transparent {
background-color: transparent !important; background-color: transparent !important;
} }

View File

@@ -1,59 +1,59 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
// //
// Border // Border
// //
.border { border: $border-width solid $border-color !important; } .border { border: $border-width solid $border-color !important; }
.border-top { border-top: $border-width solid $border-color !important; } .border-top { border-top: $border-width solid $border-color !important; }
.border-right { border-right: $border-width solid $border-color !important; } .border-right { border-right: $border-width solid $border-color !important; }
.border-bottom { border-bottom: $border-width solid $border-color !important; } .border-bottom { border-bottom: $border-width solid $border-color !important; }
.border-left { border-left: $border-width solid $border-color !important; } .border-left { border-left: $border-width solid $border-color !important; }
.border-0 { border: 0 !important; } .border-0 { border: 0 !important; }
.border-top-0 { border-top: 0 !important; } .border-top-0 { border-top: 0 !important; }
.border-right-0 { border-right: 0 !important; } .border-right-0 { border-right: 0 !important; }
.border-bottom-0 { border-bottom: 0 !important; } .border-bottom-0 { border-bottom: 0 !important; }
.border-left-0 { border-left: 0 !important; } .border-left-0 { border-left: 0 !important; }
@each $color, $value in $theme-colors { @each $color, $value in $theme-colors {
.border-#{$color} { .border-#{$color} {
border-color: $value !important; border-color: $value !important;
} }
} }
.border-white { .border-white {
border-color: $white !important; border-color: $white !important;
} }
// //
// Border-radius // Border-radius
// //
.rounded { .rounded {
border-radius: $border-radius !important; border-radius: $border-radius !important;
} }
.rounded-top { .rounded-top {
border-top-left-radius: $border-radius !important; border-top-left-radius: $border-radius !important;
border-top-right-radius: $border-radius !important; border-top-right-radius: $border-radius !important;
} }
.rounded-right { .rounded-right {
border-top-right-radius: $border-radius !important; border-top-right-radius: $border-radius !important;
border-bottom-right-radius: $border-radius !important; border-bottom-right-radius: $border-radius !important;
} }
.rounded-bottom { .rounded-bottom {
border-bottom-right-radius: $border-radius !important; border-bottom-right-radius: $border-radius !important;
border-bottom-left-radius: $border-radius !important; border-bottom-left-radius: $border-radius !important;
} }
.rounded-left { .rounded-left {
border-top-left-radius: $border-radius !important; border-top-left-radius: $border-radius !important;
border-bottom-left-radius: $border-radius !important; border-bottom-left-radius: $border-radius !important;
} }
.rounded-circle { .rounded-circle {
border-radius: 50% !important; border-radius: 50% !important;
} }
.rounded-0 { .rounded-0 {
border-radius: 0 !important; border-radius: 0 !important;
} }

View File

@@ -1,3 +1,3 @@
.clearfix { .clearfix {
@include clearfix(); @include clearfix();
} }

View File

@@ -1,38 +1,38 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
// //
// Utilities for common `display` values // Utilities for common `display` values
// //
@each $breakpoint in map-keys($grid-breakpoints) { @each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) { @include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints); $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.d#{$infix}-none { display: none !important; } .d#{$infix}-none { display: none !important; }
.d#{$infix}-inline { display: inline !important; } .d#{$infix}-inline { display: inline !important; }
.d#{$infix}-inline-block { display: inline-block !important; } .d#{$infix}-inline-block { display: inline-block !important; }
.d#{$infix}-block { display: block !important; } .d#{$infix}-block { display: block !important; }
.d#{$infix}-table { display: table !important; } .d#{$infix}-table { display: table !important; }
.d#{$infix}-table-row { display: table-row !important; } .d#{$infix}-table-row { display: table-row !important; }
.d#{$infix}-table-cell { display: table-cell !important; } .d#{$infix}-table-cell { display: table-cell !important; }
.d#{$infix}-flex { display: flex !important; } .d#{$infix}-flex { display: flex !important; }
.d#{$infix}-inline-flex { display: inline-flex !important; } .d#{$infix}-inline-flex { display: inline-flex !important; }
} }
} }
// //
// Utilities for toggling `display` in print // Utilities for toggling `display` in print
// //
@media print { @media print {
.d-print-none { display: none !important; } .d-print-none { display: none !important; }
.d-print-inline { display: inline !important; } .d-print-inline { display: inline !important; }
.d-print-inline-block { display: inline-block !important; } .d-print-inline-block { display: inline-block !important; }
.d-print-block { display: block !important; } .d-print-block { display: block !important; }
.d-print-table { display: table !important; } .d-print-table { display: table !important; }
.d-print-table-row { display: table-row !important; } .d-print-table-row { display: table-row !important; }
.d-print-table-cell { display: table-cell !important; } .d-print-table-cell { display: table-cell !important; }
.d-print-flex { display: flex !important; } .d-print-flex { display: flex !important; }
.d-print-inline-flex { display: inline-flex !important; } .d-print-inline-flex { display: inline-flex !important; }
} }

View File

@@ -1,52 +1,52 @@
// Credit: Nicolas Gallagher and SUIT CSS. // Credit: Nicolas Gallagher and SUIT CSS.
.embed-responsive { .embed-responsive {
position: relative; position: relative;
display: block; display: block;
width: 100%; width: 100%;
padding: 0; padding: 0;
overflow: hidden; overflow: hidden;
&::before { &::before {
display: block; display: block;
content: ""; content: "";
} }
.embed-responsive-item, .embed-responsive-item,
iframe, iframe,
embed, embed,
object, object,
video { video {
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
border: 0; border: 0;
} }
} }
.embed-responsive-21by9 { .embed-responsive-21by9 {
&::before { &::before {
padding-top: percentage(9 / 21); padding-top: percentage(9 / 21);
} }
} }
.embed-responsive-16by9 { .embed-responsive-16by9 {
&::before { &::before {
padding-top: percentage(9 / 16); padding-top: percentage(9 / 16);
} }
} }
.embed-responsive-4by3 { .embed-responsive-4by3 {
&::before { &::before {
padding-top: percentage(3 / 4); padding-top: percentage(3 / 4);
} }
} }
.embed-responsive-1by1 { .embed-responsive-1by1 {
&::before { &::before {
padding-top: percentage(1 / 1); padding-top: percentage(1 / 1);
} }
} }

View File

@@ -1,51 +1,51 @@
// stylelint-disable declaration-no-important // stylelint-disable declaration-no-important
// Flex variation // Flex variation
// //
// Custom styles for additional flex alignment options. // Custom styles for additional flex alignment options.
@each $breakpoint in map-keys($grid-breakpoints) { @each $breakpoint in map-keys($grid-breakpoints) {
@include media-breakpoint-up($breakpoint) { @include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints); $infix: breakpoint-infix($breakpoint, $grid-breakpoints);
.flex#{$infix}-row { flex-direction: row !important; } .flex#{$infix}-row { flex-direction: row !important; }
.flex#{$infix}-column { flex-direction: column !important; } .flex#{$infix}-column { flex-direction: column !important; }
.flex#{$infix}-row-reverse { flex-direction: row-reverse !important; } .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }
.flex#{$infix}-column-reverse { flex-direction: column-reverse !important; } .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }
.flex#{$infix}-wrap { flex-wrap: wrap !important; } .flex#{$infix}-wrap { flex-wrap: wrap !important; }
.flex#{$infix}-nowrap { flex-wrap: nowrap !important; } .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }
.flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; } .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }
.flex#{$infix}-fill { flex: 1 1 auto !important; } .flex#{$infix}-fill { flex: 1 1 auto !important; }
.flex#{$infix}-grow-0 { flex-grow: 0 !important; } .flex#{$infix}-grow-0 { flex-grow: 0 !important; }
.flex#{$infix}-grow-1 { flex-grow: 1 !important; } .flex#{$infix}-grow-1 { flex-grow: 1 !important; }
.flex#{$infix}-shrink-0 { flex-shrink: 0 !important; } .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }
.flex#{$infix}-shrink-1 { flex-shrink: 1 !important; } .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }
.justify-content#{$infix}-start { justify-content: flex-start !important; } .justify-content#{$infix}-start { justify-content: flex-start !important; }
.justify-content#{$infix}-end { justify-content: flex-end !important; } .justify-content#{$infix}-end { justify-content: flex-end !important; }
.justify-content#{$infix}-center { justify-content: center !important; } .justify-content#{$infix}-center { justify-content: center !important; }
.justify-content#{$infix}-between { justify-content: space-between !important; } .justify-content#{$infix}-between { justify-content: space-between !important; }
.justify-content#{$infix}-around { justify-content: space-around !important; } .justify-content#{$infix}-around { justify-content: space-around !important; }
.align-items#{$infix}-start { align-items: flex-start !important; } .align-items#{$infix}-start { align-items: flex-start !important; }
.align-items#{$infix}-end { align-items: flex-end !important; } .align-items#{$infix}-end { align-items: flex-end !important; }
.align-items#{$infix}-center { align-items: center !important; } .align-items#{$infix}-center { align-items: center !important; }
.align-items#{$infix}-baseline { align-items: baseline !important; } .align-items#{$infix}-baseline { align-items: baseline !important; }
.align-items#{$infix}-stretch { align-items: stretch !important; } .align-items#{$infix}-stretch { align-items: stretch !important; }
.align-content#{$infix}-start { align-content: flex-start !important; } .align-content#{$infix}-start { align-content: flex-start !important; }
.align-content#{$infix}-end { align-content: flex-end !important; } .align-content#{$infix}-end { align-content: flex-end !important; }
.align-content#{$infix}-center { align-content: center !important; } .align-content#{$infix}-center { align-content: center !important; }
.align-content#{$infix}-between { align-content: space-between !important; } .align-content#{$infix}-between { align-content: space-between !important; }
.align-content#{$infix}-around { align-content: space-around !important; } .align-content#{$infix}-around { align-content: space-around !important; }
.align-content#{$infix}-stretch { align-content: stretch !important; } .align-content#{$infix}-stretch { align-content: stretch !important; }
.align-self#{$infix}-auto { align-self: auto !important; } .align-self#{$infix}-auto { align-self: auto !important; }
.align-self#{$infix}-start { align-self: flex-start !important; } .align-self#{$infix}-start { align-self: flex-start !important; }
.align-self#{$infix}-end { align-self: flex-end !important; } .align-self#{$infix}-end { align-self: flex-end !important; }
.align-self#{$infix}-center { align-self: center !important; } .align-self#{$infix}-center { align-self: center !important; }
.align-self#{$infix}-baseline { align-self: baseline !important; } .align-self#{$infix}-baseline { align-self: baseline !important; }
.align-self#{$infix}-stretch { align-self: stretch !important; } .align-self#{$infix}-stretch { align-self: stretch !important; }
} }
} }

Some files were not shown because too many files have changed in this diff Show More