From d6406cdf7c8c328ff0cc79d851ec8b2ed80b0486 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9E=AC=EA=B5=AD?= <97966640+jk6722@users.noreply.github.com> Date: Sun, 19 Nov 2023 09:14:03 +0900 Subject: [PATCH] Feat/#42/api jaeguk (#48) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 좋아요 버튼 이벤트 버블링 방지 * feat: 지도 마커 정보 API 연결 * feat: 마커 정보 데이터 불러오는 Axios 함수 추가 * feat: 검색어 입력 후 버튼 클릭시 검색 페이지로 이동 * feat: 마커 상세 카드 클릭시 상세 페이지로 이동 * style: 마커 상세 카드 닫기 버튼 z-index 조절 * feat: 소셜 로그인 컴포넌트 따로 분리 * feat: 로그인 버튼 하단에 회원가입, 아이디 찾기, 비밀번호 찾기 버튼 추가 * chore: 파일 경로 이동 * chore: 파일 import 경로 수정 * feat: 로그인 로직 구현 (추후 테스트 필요) * feat: 후기 페이지 제목 글꼴 변경 * chore: 불필요한 import 제거 * feat: 검색바 입력 후 페이지 이동 함수 분리 * feat: 분리된 함수 사용해서 검색 후 페이지 이동 * chore: 포스팅 상세 타입 명칭 변경 * chore: handleClickSearchProgram인자로 navigate 받도록 변경 * chore: 함수 인자로 navigate 넘겨주도록 변경 * chore: props 명칭 변경에 따른 수정 * style: 메인 페이지 width 1440px로 고정 * style: 메인 배너 이미지 변경 * feat: 로그인 성공시 Axios 기본 헤더에 토큰 추가 * fix: react-quill css파일 별도 분리 * fix: 소셜 로그인 아이콘 import 방식 변경 * chore: 사용하지 않는 변수 제거 * chore: 현재 사용하지 않는 변수 주석처리 --- src/App.tsx | 2 +- src/apis/map/index.ts | 3 + src/assets/main/banner_image.svg | 18 +- src/components/Button/LikeButton.tsx | 25 +- src/functions/index.ts | 12 + src/pages/board/Introduction.tsx | 13 +- src/pages/login/Login.tsx | 103 +-- src/pages/login/LoginNavLink.tsx | 36 + src/pages/login/SocialLogin.tsx | 58 ++ src/pages/login/functions/index.ts | 14 + src/pages/login/{ => redir}/KakaoRedir.tsx | 0 src/pages/main/Banner.tsx | 4 +- src/pages/main/HotProgram.tsx | 4 +- src/pages/main/Main.tsx | 1 + src/pages/main/PageNav.tsx | 14 +- src/pages/main/Uploaded.tsx | 5 +- src/pages/map/Map.tsx | 67 +- src/pages/map/components/MapCard.tsx | 51 +- src/pages/write/index.tsx | 2 +- src/style/quill.snow.css | 984 +++++++++++++++++++++ 20 files changed, 1272 insertions(+), 144 deletions(-) create mode 100644 src/apis/map/index.ts create mode 100644 src/functions/index.ts create mode 100644 src/pages/login/LoginNavLink.tsx create mode 100644 src/pages/login/SocialLogin.tsx create mode 100644 src/pages/login/functions/index.ts rename src/pages/login/{ => redir}/KakaoRedir.tsx (100%) create mode 100644 src/style/quill.snow.css diff --git a/src/App.tsx b/src/App.tsx index 80818b4..132a212 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,7 +3,7 @@ import Main from './pages/main/Main'; import Map from './pages/map/Map'; import { GlobalStyle } from './style/GlobalStyle'; import Login from './pages/login/Login'; -import KakaoRedir from './pages/login/KakaoRedir'; +import KakaoRedir from './pages/login/redir/KakaoRedir'; import Layout from './components/Header/Layout'; import Search from './pages/Search'; import Board from './pages/board/Board'; diff --git a/src/apis/map/index.ts b/src/apis/map/index.ts new file mode 100644 index 0000000..28950cb --- /dev/null +++ b/src/apis/map/index.ts @@ -0,0 +1,3 @@ +import Axios from '..'; + +export const fetchMapMarker = () => () => Axios.get('/programs/map'); diff --git a/src/assets/main/banner_image.svg b/src/assets/main/banner_image.svg index 55f1c65..6032520 100644 --- a/src/assets/main/banner_image.svg +++ b/src/assets/main/banner_image.svg @@ -1,9 +1,19 @@ - - + + + + - + - + + + + + + + + + diff --git a/src/components/Button/LikeButton.tsx b/src/components/Button/LikeButton.tsx index 7fe3907..f79f482 100644 --- a/src/components/Button/LikeButton.tsx +++ b/src/components/Button/LikeButton.tsx @@ -11,16 +11,20 @@ interface Props { const LikeButton: React.FC = ({ isLike, setIsLike, type }) => { // Todo: 인자로 id 전달받아서 서버에 찜 목록에 등록하는 API 연결 - const handleClick = useCallback(() => { - switch (type) { - case 'program': - setIsLike(prev => !prev); - break; - case 'posting': - setIsLike(prev => !prev); - break; - } - }, [isLike]); + const handleClick = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation(); + switch (type) { + case 'program': + setIsLike(prev => !prev); + break; + case 'posting': + setIsLike(prev => !prev); + break; + } + }, + [isLike], + ); return ( @@ -36,6 +40,7 @@ const LikeButton: React.FC = ({ isLike, setIsLike, type }) => { export default LikeButton; const Wrapper = styled.div` + z-index: 3; img { width: 100%; height: 100%; diff --git a/src/functions/index.ts b/src/functions/index.ts new file mode 100644 index 0000000..6fa714b --- /dev/null +++ b/src/functions/index.ts @@ -0,0 +1,12 @@ +import { NavigateFunction } from 'react-router-dom'; + +export const handleClickSearchProgram = ( + searchInput: string, + setSearchInput: React.Dispatch>, + navigate: NavigateFunction, +) => { + // 검색 후 페이지 이동 + console.log('@@@@'); + navigate(`/search?keyword=${searchInput}`); + setSearchInput(''); +}; diff --git a/src/pages/board/Introduction.tsx b/src/pages/board/Introduction.tsx index 7a92aa6..b2d70b6 100644 --- a/src/pages/board/Introduction.tsx +++ b/src/pages/board/Introduction.tsx @@ -1,4 +1,4 @@ -import { B2, H1 } from '@/style/fonts/StyledFonts'; +import { B2 } from '@/style/fonts/StyledFonts'; import React from 'react'; import styled from 'styled-components'; @@ -15,7 +15,7 @@ const Introduction: React.FC = ({ title, imageSrc, description }) => { -

{title}

+ {title} {description}
@@ -34,6 +34,15 @@ const Container = styled.div` gap: 55px; `; +const Title = styled.pre` + color: var(--gray-900, #15191d); + font-family: 'Recipekorea'; + font-size: 36px; + font-style: normal; + font-weight: 400; + line-height: 150%; /* 54px */ +`; + const ImageWrapper = styled.div` //캐릭터 들어갈 곳 width: 180px; diff --git a/src/pages/login/Login.tsx b/src/pages/login/Login.tsx index 25cf01b..da87996 100644 --- a/src/pages/login/Login.tsx +++ b/src/pages/login/Login.tsx @@ -1,9 +1,12 @@ -import { B2Bold, B3, H1 } from '@/style/fonts/StyledFonts'; import { useState } from 'react'; import styled from 'styled-components'; -import Naver from '@/assets/icons/icon-naver.svg'; -import Kakao from '@/assets/icons/icon-kakao.svg'; -import Google from '@/assets/icons/icon-google.svg'; +import { useNavigate } from 'react-router-dom'; + +import Axios from '@/apis'; +import { B2Bold, B3, H1 } from '@/style/fonts/StyledFonts'; +import SocialLogin from './SocialLogin'; +import LoginNavLink from './LoginNavLink'; +import { onLoginSuccess } from './functions'; interface UserInputType { id: string; @@ -11,20 +14,34 @@ interface UserInputType { } const Login = () => { - const REST_API_KEY = import.meta.env.VITE_KAKAO_REST_API_KEY; //REST API KEY - const REDIRECT_URI = `${window.location.origin}/kakao/login`; //REDIRECT URI - - // oauth 요청 URL - const kakaoURL = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`; - const [userInput, setUserInput] = useState({ id: '', password: '', }); + const [isError, setIsError] = useState(false); + const navigate = useNavigate(); + + const handleLogin = async () => { + try { + const res = await Axios.post('/auth/login', null, { + params: { loginId: userInput.id, loginPassword: userInput.password }, + }); + onLoginSuccess(res); + navigate('/'); + } catch (e) { + // 비밀번호 불일치시 메시지 + setIsError(true); + setTimeout(() => { + setIsError(false); + }, 4000); + console.error(e); + } finally { + setUserInput(prev => ({ ...prev, password: '' })); + } + }; - const handleKakaoLogin = () => { - // 카카오 로그인 주소 - window.location.href = kakaoURL; + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.code === 'Enter') handleLogin(); }; const handleChangeId = (e: React.ChangeEvent) => { @@ -54,29 +71,27 @@ const Login = () => { {/* Password */} + {isError && ( + + + 아이디 또는 비밀번호가 일치하지 않습니다. + + + )} - - - - {/* 네이버 로그인 */} - - naver - - {/* 카카오 로그인 */} - - kakao - - {/* 구글 로그인 */} - - google - - + {/* 소셜 로그인 */} + + {/* 네비게이션 */} + ); }; @@ -110,10 +125,18 @@ const LoginContainer = styled.div` flex-direction: column; align-items: flex-start; + position: relative; + width: 100%; gap: 20px; `; +const ErrorMessage = styled.div` + position: absolute; + bottom: -30px; + left: 28px; +`; + const Input = styled.input` width: 100%; height: 56px; @@ -148,25 +171,3 @@ const Button = styled.button` border-radius: 10px; background: var(--Sub-3, #ff7d2c); `; - -const SocialLoginContainer = styled.div` - display: flex; - align-items: flex-start; - - gap: 16px; -`; - -const SocialLoginButton = styled.div` - display: flex; - align-items: center; - justify-content: center; - - width: 56px; - height: 56px; - flex-shrink: 0; - - background: #f6f6f6; - border-radius: 50%; - - cursor: pointer; -`; diff --git a/src/pages/login/LoginNavLink.tsx b/src/pages/login/LoginNavLink.tsx new file mode 100644 index 0000000..f674df6 --- /dev/null +++ b/src/pages/login/LoginNavLink.tsx @@ -0,0 +1,36 @@ +import { B3 } from '@/style/fonts/StyledFonts'; +import { Link } from 'react-router-dom'; +import styled from 'styled-components'; + +const LoginNavLink = () => { + return ( + + + 회원가입 + + + 아이디 찾기 + + 비밀번호 찾기 + + ); +}; + +export default LoginNavLink; + +const Container = styled.div` + display: flex; + align-items: center; + justify-items: center; + gap: 21px; + + pre { + width: 88px; + } +`; + +const Divider = styled.div` + width: 1px; + height: 20px; + background: var(--gray-300, #d2d7dc); +`; diff --git a/src/pages/login/SocialLogin.tsx b/src/pages/login/SocialLogin.tsx new file mode 100644 index 0000000..69a24fa --- /dev/null +++ b/src/pages/login/SocialLogin.tsx @@ -0,0 +1,58 @@ +import styled from 'styled-components'; + +import Naver from '@/assets/icons/icon-naver.svg'; +import Kakao from '@/assets/icons/icon-kakao.svg'; +import Google from '@/assets/icons/icon-google.svg'; + +const SocialLogin = () => { + const REST_API_KEY = import.meta.env.VITE_KAKAO_REST_API_KEY; //REST API KEY + const REDIRECT_URI = `${window.location.origin}/kakao/login`; //REDIRECT URI + // oauth 요청 URL + const kakaoURL = `https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}&response_type=code`; + + const handleKakaoLogin = () => { + // 카카오 로그인 주소 + window.location.href = kakaoURL; + }; + + return ( + + {/* 네이버 로그인 */} + + naver + + {/* 카카오 로그인 */} + + kakao + + {/* 구글 로그인 */} + + google + + + ); +}; + +export default SocialLogin; + +const SocialLoginContainer = styled.div` + display: flex; + align-items: flex-start; + + gap: 16px; +`; + +const SocialLoginButton = styled.div` + display: flex; + align-items: center; + justify-content: center; + + width: 56px; + height: 56px; + flex-shrink: 0; + + background: #f6f6f6; + border-radius: 50%; + + cursor: pointer; +`; diff --git a/src/pages/login/functions/index.ts b/src/pages/login/functions/index.ts new file mode 100644 index 0000000..e2dc1d5 --- /dev/null +++ b/src/pages/login/functions/index.ts @@ -0,0 +1,14 @@ +import Axios from '@/apis'; +import { AxiosResponse } from 'axios'; + +export const onLoginSuccess = (res: AxiosResponse) => { + const { accessToken, refreshToken } = res?.data?.result; + refreshToken; + Axios.defaults.headers.common['Authorization'] = `Bearer ${accessToken}`; +}; + +// export const onSilentRefresh = async () => { +// try { +// const res = await Axios.post(TOKEN) +// } +// } diff --git a/src/pages/login/KakaoRedir.tsx b/src/pages/login/redir/KakaoRedir.tsx similarity index 100% rename from src/pages/login/KakaoRedir.tsx rename to src/pages/login/redir/KakaoRedir.tsx diff --git a/src/pages/main/Banner.tsx b/src/pages/main/Banner.tsx index ce3b055..13a1b00 100644 --- a/src/pages/main/Banner.tsx +++ b/src/pages/main/Banner.tsx @@ -38,8 +38,8 @@ const InnerContainer = styled.div` align-items: center; justify-content: space-between; - width: 100%; - padding: 0 360px; + width: 1440px; + margin: auto; `; const LeftBox = styled.div` diff --git a/src/pages/main/HotProgram.tsx b/src/pages/main/HotProgram.tsx index 99f31f2..c0306c8 100644 --- a/src/pages/main/HotProgram.tsx +++ b/src/pages/main/HotProgram.tsx @@ -48,8 +48,8 @@ const Container = styled.div` position: relative; - width: 100%; - padding: 0 360px 260px; + width: 1440px; + margin: 0 auto 260px; `; const TextContainer = styled.div` diff --git a/src/pages/main/Main.tsx b/src/pages/main/Main.tsx index 0a36468..9d90e30 100644 --- a/src/pages/main/Main.tsx +++ b/src/pages/main/Main.tsx @@ -25,5 +25,6 @@ const Container = styled.div` flex-direction: column; align-items: center; + width: 100%; gap: 120px; `; diff --git a/src/pages/main/PageNav.tsx b/src/pages/main/PageNav.tsx index 83ff5f8..9dfff4b 100644 --- a/src/pages/main/PageNav.tsx +++ b/src/pages/main/PageNav.tsx @@ -3,16 +3,13 @@ import { useState } from 'react'; import styled from 'styled-components'; import NavCard from './components/NavCard'; import { NavData } from '@/constants/main'; +import { handleClickSearchProgram } from '@/functions'; import { useNavigate } from 'react-router-dom'; const PageNav = () => { const [searchInput, setSearchInput] = useState(''); const navigate = useNavigate(); - const handleSearch = () => { - navigate(`/search?keyword=${searchInput}`); - }; - return ( @@ -20,7 +17,9 @@ const PageNav = () => { placeHolder="어디로 떠나고 싶으신가요?" searchInput={searchInput} setSearchInput={setSearchInput} - handleSubmit={handleSearch} + handleSubmit={() => + handleClickSearchProgram(searchInput, setSearchInput, navigate) + } /> @@ -39,9 +38,8 @@ const Container = styled.div` flex-direction: column; align-items: center; - width: 100%; - padding: 0 360px; - + width: 1440px; + margin: auto; gap: 120px; `; diff --git a/src/pages/main/Uploaded.tsx b/src/pages/main/Uploaded.tsx index 60251e3..d3724d9 100644 --- a/src/pages/main/Uploaded.tsx +++ b/src/pages/main/Uploaded.tsx @@ -41,9 +41,8 @@ const Container = styled.div` position: relative; - width: 100%; - padding: 0 360px; - margin-top: 44px; + width: 1440px; + margin: 44px auto 0; gap: 64px; `; diff --git a/src/pages/map/Map.tsx b/src/pages/map/Map.tsx index e94b0c4..206ce3c 100644 --- a/src/pages/map/Map.tsx +++ b/src/pages/map/Map.tsx @@ -5,44 +5,31 @@ import MapCard from './components/MapCard'; import styled from 'styled-components'; import SearchBar from '@/components/SearchBar/SearchBar'; import useOnClickOutside from '@/hooks/useOnClickOutside'; +import { useQuery } from 'react-query'; +import { fetchMapMarker } from '@/apis/map'; +import Loading from '@/components/Loading/Loading'; +import { handleClickSearchProgram } from '@/functions'; +import { useNavigate } from 'react-router-dom'; interface markerDataType { - lat: number; - lng: number; - imageSrc: string; - title: string; - period: string; + id: number; + latitude: number; + longitude: number; + photoUrl: string; + programName: string; + recruitStartDate: string; + recruitEndDate: string; } -const markerData: markerDataType[] = [ - // API 받아오기 전 임시 데이터 - { - lat: 37.566566, - lng: 126.979192, - imageSrc: '/src/assets/map/card_thumbnail.svg', - title: '부여 행복여행 지원사업 참가자 모집', - period: '2023.10.01 - 2023.11.09', - }, - { - lat: 37.666566, - lng: 126.979192, - imageSrc: '/src/assets/map/card_thumbnail.svg', - title: '울산 행복여행 지원사업 참가자 모집', - period: '2023.10.01 - 2023.11.09', - }, - { - lat: 37.596566, - lng: 126.97002, - imageSrc: '/src/assets/map/card_thumbnail.svg', - title: '광주 행복여행 지원사업 참가자 모집', - period: '2023.10.01 - 2023.11.09', - }, -]; - const MapPage = () => { const [selected, setSelected] = useState(-1); const [isModalOpen, setIsModalOpen] = useState(false); const [searchInput, setSearchInput] = useState(''); + const { isLoading, data } = useQuery(['marker'], fetchMapMarker(), { + cacheTime: 500005, + staleTime: 500000, + }); + const navigate = useNavigate(); const cardRef = useRef(null); @@ -58,10 +45,11 @@ const MapPage = () => { }; }, []); - const handleClickSearch = () => { - // 검색 후 페이지 이동 - setSearchInput(''); - }; + if (isLoading) return ; + + const markerData: markerDataType[] = data?.data?.result + ? data?.data?.result + : []; return ( @@ -69,8 +57,10 @@ const MapPage = () => { )} @@ -78,16 +68,19 @@ const MapPage = () => { searchInput={searchInput} setSearchInput={setSearchInput} placeHolder="관심있는 여행지가 있으신가요?" - handleSubmit={handleClickSearch} + handleSubmit={() => + handleClickSearchProgram(searchInput, setSearchInput, navigate) + } /> + - {markerData.map(({ lat, lng }, idx) => ( + {markerData?.map(({ latitude: lat, longitude: lng, id }, idx) => ( { index={idx} setSelected={setSelected} setIsModalOpen={setIsModalOpen} - key={idx} + key={id} /> ))} diff --git a/src/pages/map/components/MapCard.tsx b/src/pages/map/components/MapCard.tsx index f41b6f2..51b48c8 100644 --- a/src/pages/map/components/MapCard.tsx +++ b/src/pages/map/components/MapCard.tsx @@ -1,44 +1,57 @@ -import React from 'react'; +import React, { useState } from 'react'; +import { useNavigate } from 'react-router-dom'; import styled from 'styled-components'; + import { B1Bold, B3 } from '../../../style/fonts/StyledFonts'; +import LikeButton from '@/components/Button/LikeButton'; import CloseIcon from '@/assets/icons/icon-close.svg'; interface Props { - imageSrc: string; - title: string; + id: number; + photoUrl: string; + programName: string; period: string; setIsModalOpen: React.Dispatch>; setSelected: React.Dispatch>; cardRef: React.RefObject; + isLiked: boolean; } const MapCard: React.FC = ({ - imageSrc, - title, + id, + photoUrl, + programName, period, setIsModalOpen, setSelected, cardRef, + isLiked, }) => { - const handleClose = () => { + const navigate = useNavigate(); + const handleClick = () => { + navigate(`/detailProgram/${programName}/${id}`); + }; + + const handleClose = (e: React.MouseEvent) => { + e.stopPropagation(); setIsModalOpen(false); setSelected(-1); }; + const [isLike, setIsLike] = useState(isLiked); + return ( - + - thumbNail + thumbNail - {title} + {programName} {period} - - - + close @@ -58,6 +71,8 @@ const Container = styled.div` height: 360px; flex-shrink: 0; + cursor: pointer; + padding: 20px; border-radius: 30px; @@ -91,6 +106,7 @@ const CloseButton = styled.div` top: 10px; right: 10px; + z-index: 3; cursor: pointer; img { @@ -106,14 +122,3 @@ const TextContainer = styled.div` gap: 4px; margin: 0; `; - -const LikeButton = styled.div` - width: 48px; - height: 48px; - flex-shrink: 0; - - fill: var(--main_1, #fff); - stroke-width: 1px; - stroke: var(--grey-300, #d2d7dc); - backdrop-filter: blur(2.5px); -`; diff --git a/src/pages/write/index.tsx b/src/pages/write/index.tsx index 22c532e..f5a65fd 100644 --- a/src/pages/write/index.tsx +++ b/src/pages/write/index.tsx @@ -4,11 +4,11 @@ import ReactQuill, { Quill } from 'react-quill'; import styled from 'styled-components'; import ImageResize from 'quill-image-resize-module-react'; +import '@/style/quill.snow.css'; import DropDown from '@/components/DropDown/DropDown'; import InputTags from './components/InputTags'; import RoundedButton from '@/components/Button/RoundedButton'; import { B3 } from '@/style/fonts/StyledFonts'; -import 'react-quill/dist/quill.snow.css'; import { imageHandler, isOkToPost } from './functions'; import { DropDownData } from '@/constants/write'; import InputFile from './components/InputFile'; diff --git a/src/style/quill.snow.css b/src/style/quill.snow.css new file mode 100644 index 0000000..f3c1d7b --- /dev/null +++ b/src/style/quill.snow.css @@ -0,0 +1,984 @@ +/* ! + * Quill Editor v1.3.7 + * https://quilljs.com/ + * Copyright (c) 2014, Jason Chen + * Copyright (c) 2013, salesforce.com + */ +.ql-container { + box-sizing: border-box; + font-family: Helvetica, Arial, sans-serif; + font-size: 13px; + height: 100%; + margin: 0px; + /* position: relative; */ +} +.ql-container.ql-disabled .ql-tooltip { + visibility: hidden; +} +.ql-container.ql-disabled .ql-editor ul[data-checked] > li::before { + pointer-events: none; +} +.ql-clipboard { + left: -100000px; + height: 1px; + overflow-y: hidden; + position: absolute; + top: 50%; +} +.ql-clipboard p { + margin: 0; + padding: 0; +} +.ql-editor { + box-sizing: border-box; + text-indent: 25.13px; + line-height: 1.42; + height: 100%; + outline: none; + overflow-y: auto; + padding: 20px 15px 12px; + tab-size: 4; + -moz-tab-size: 4; + text-align: left; + white-space: pre-wrap; + word-wrap: break-word; +} +.ql-editor > * { + cursor: text; +} +.ql-editor p { + + color: var(--grey-900, #15191D); + /* Body 01 */ + font-family: SUIT; + font-size: 20px; + font-style: normal; + font-weight: 500; + line-height: 150%; /* 30px */ +} +.ql-editor p, +.ql-editor ol, +.ql-editor ul, +.ql-editor pre, +.ql-editor blockquote, +.ql-editor h1, +.ql-editor h2, +.ql-editor h3, +.ql-editor h4, +.ql-editor h5, +.ql-editor h6 { + margin: 0; + padding: 0; + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} + +.ql-editor ol, +.ql-editor ul { + padding-left: 1.5em; +} +.ql-editor ol > li, +.ql-editor ul > li { + list-style-type: none; +} +.ql-editor ul > li::before { + content: '\2022'; +} +.ql-editor ul[data-checked=true], +.ql-editor ul[data-checked=false] { + pointer-events: none; +} +.ql-editor ul[data-checked=true] > li *, +.ql-editor ul[data-checked=false] > li * { + pointer-events: all; +} +.ql-editor ul[data-checked=true] > li::before, +.ql-editor ul[data-checked=false] > li::before { + color: #777; + cursor: pointer; + pointer-events: all; +} +.ql-editor ul[data-checked=true] > li::before { + content: '\2611'; +} +.ql-editor ul[data-checked=false] > li::before { + content: '\2610'; +} +.ql-editor li::before { + display: inline-block; + white-space: nowrap; + width: 1.2em; +} +.ql-editor li:not(.ql-direction-rtl)::before { + margin-left: -1.5em; + margin-right: 0.3em; + text-align: right; +} +.ql-editor li.ql-direction-rtl::before { + margin-left: 0.3em; + margin-right: -1.5em; +} +.ql-editor ol li:not(.ql-direction-rtl), +.ql-editor ul li:not(.ql-direction-rtl) { + padding-left: 1.5em; +} +.ql-editor ol li.ql-direction-rtl, +.ql-editor ul li.ql-direction-rtl { + padding-right: 1.5em; +} +.ql-editor ol li { + counter-reset: list-1 list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; + counter-increment: list-0; +} +.ql-editor ol li:before { + content: counter(list-0, decimal) '. '; +} +.ql-editor ol li.ql-indent-1 { + counter-increment: list-1; +} +.ql-editor ol li.ql-indent-1:before { + content: counter(list-1, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-1 { + counter-reset: list-2 list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-2 { + counter-increment: list-2; +} +.ql-editor ol li.ql-indent-2:before { + content: counter(list-2, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-2 { + counter-reset: list-3 list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-3 { + counter-increment: list-3; +} +.ql-editor ol li.ql-indent-3:before { + content: counter(list-3, decimal) '. '; +} +.ql-editor ol li.ql-indent-3 { + counter-reset: list-4 list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-4 { + counter-increment: list-4; +} +.ql-editor ol li.ql-indent-4:before { + content: counter(list-4, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-4 { + counter-reset: list-5 list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-5 { + counter-increment: list-5; +} +.ql-editor ol li.ql-indent-5:before { + content: counter(list-5, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-5 { + counter-reset: list-6 list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-6 { + counter-increment: list-6; +} +.ql-editor ol li.ql-indent-6:before { + content: counter(list-6, decimal) '. '; +} +.ql-editor ol li.ql-indent-6 { + counter-reset: list-7 list-8 list-9; +} +.ql-editor ol li.ql-indent-7 { + counter-increment: list-7; +} +.ql-editor ol li.ql-indent-7:before { + content: counter(list-7, lower-alpha) '. '; +} +.ql-editor ol li.ql-indent-7 { + counter-reset: list-8 list-9; +} +.ql-editor ol li.ql-indent-8 { + counter-increment: list-8; +} +.ql-editor ol li.ql-indent-8:before { + content: counter(list-8, lower-roman) '. '; +} +.ql-editor ol li.ql-indent-8 { + counter-reset: list-9; +} +.ql-editor ol li.ql-indent-9 { + counter-increment: list-9; +} +.ql-editor ol li.ql-indent-9:before { + content: counter(list-9, decimal) '. '; +} +.ql-editor .ql-indent-1:not(.ql-direction-rtl) { + padding-left: 3em; +} +.ql-editor li.ql-indent-1:not(.ql-direction-rtl) { + padding-left: 4.5em; +} +.ql-editor .ql-indent-1.ql-direction-rtl.ql-align-right { + padding-right: 3em; +} +.ql-editor li.ql-indent-1.ql-direction-rtl.ql-align-right { + padding-right: 4.5em; +} +.ql-editor .ql-indent-2:not(.ql-direction-rtl) { + padding-left: 6em; +} +.ql-editor li.ql-indent-2:not(.ql-direction-rtl) { + padding-left: 7.5em; +} +.ql-editor .ql-indent-2.ql-direction-rtl.ql-align-right { + padding-right: 6em; +} +.ql-editor li.ql-indent-2.ql-direction-rtl.ql-align-right { + padding-right: 7.5em; +} +.ql-editor .ql-indent-3:not(.ql-direction-rtl) { + padding-left: 9em; +} +.ql-editor li.ql-indent-3:not(.ql-direction-rtl) { + padding-left: 10.5em; +} +.ql-editor .ql-indent-3.ql-direction-rtl.ql-align-right { + padding-right: 9em; +} +.ql-editor li.ql-indent-3.ql-direction-rtl.ql-align-right { + padding-right: 10.5em; +} +.ql-editor .ql-indent-4:not(.ql-direction-rtl) { + padding-left: 12em; +} +.ql-editor li.ql-indent-4:not(.ql-direction-rtl) { + padding-left: 13.5em; +} +.ql-editor .ql-indent-4.ql-direction-rtl.ql-align-right { + padding-right: 12em; +} +.ql-editor li.ql-indent-4.ql-direction-rtl.ql-align-right { + padding-right: 13.5em; +} +.ql-editor .ql-indent-5:not(.ql-direction-rtl) { + padding-left: 15em; +} +.ql-editor li.ql-indent-5:not(.ql-direction-rtl) { + padding-left: 16.5em; +} +.ql-editor .ql-indent-5.ql-direction-rtl.ql-align-right { + padding-right: 15em; +} +.ql-editor li.ql-indent-5.ql-direction-rtl.ql-align-right { + padding-right: 16.5em; +} +.ql-editor .ql-indent-6:not(.ql-direction-rtl) { + padding-left: 18em; +} +.ql-editor li.ql-indent-6:not(.ql-direction-rtl) { + padding-left: 19.5em; +} +.ql-editor .ql-indent-6.ql-direction-rtl.ql-align-right { + padding-right: 18em; +} +.ql-editor li.ql-indent-6.ql-direction-rtl.ql-align-right { + padding-right: 19.5em; +} +.ql-editor .ql-indent-7:not(.ql-direction-rtl) { + padding-left: 21em; +} +.ql-editor li.ql-indent-7:not(.ql-direction-rtl) { + padding-left: 22.5em; +} +.ql-editor .ql-indent-7.ql-direction-rtl.ql-align-right { + padding-right: 21em; +} +.ql-editor li.ql-indent-7.ql-direction-rtl.ql-align-right { + padding-right: 22.5em; +} +.ql-editor .ql-indent-8:not(.ql-direction-rtl) { + padding-left: 24em; +} +.ql-editor li.ql-indent-8:not(.ql-direction-rtl) { + padding-left: 25.5em; +} +.ql-editor .ql-indent-8.ql-direction-rtl.ql-align-right { + padding-right: 24em; +} +.ql-editor li.ql-indent-8.ql-direction-rtl.ql-align-right { + padding-right: 25.5em; +} +.ql-editor .ql-indent-9:not(.ql-direction-rtl) { + padding-left: 27em; +} +.ql-editor li.ql-indent-9:not(.ql-direction-rtl) { + padding-left: 28.5em; +} +.ql-editor .ql-indent-9.ql-direction-rtl.ql-align-right { + padding-right: 27em; +} +.ql-editor li.ql-indent-9.ql-direction-rtl.ql-align-right { + padding-right: 28.5em; +} +.ql-editor .ql-video { + display: block; + max-width: 100%; +} +.ql-editor .ql-video.ql-align-center { + margin: 0 auto; +} +.ql-editor .ql-video.ql-align-right { + margin: 0 0 0 auto; +} +.ql-editor .ql-bg-black { + background-color: #000; +} +.ql-editor .ql-bg-red { + background-color: #e60000; +} +.ql-editor .ql-bg-orange { + background-color: #f90; +} +.ql-editor .ql-bg-yellow { + background-color: #ff0; +} +.ql-editor .ql-bg-green { + background-color: #008a00; +} +.ql-editor .ql-bg-blue { + background-color: #06c; +} +.ql-editor .ql-bg-purple { + background-color: #93f; +} +.ql-editor .ql-color-white { + color: #fff; +} +.ql-editor .ql-color-red { + color: #e60000; +} +.ql-editor .ql-color-orange { + color: #f90; +} +.ql-editor .ql-color-yellow { + color: #ff0; +} +.ql-editor .ql-color-green { + color: #008a00; +} +.ql-editor .ql-color-blue { + color: #06c; +} +.ql-editor .ql-color-purple { + color: #93f; +} +.ql-editor .ql-font-serif { + font-family: Georgia, Times New Roman, serif; +} +.ql-editor .ql-font-monospace { + font-family: Monaco, Courier New, monospace; +} +.ql-editor .ql-size-small { + font-size: 0.75em; +} +.ql-editor .ql-size-large { + font-size: 1.5em; +} +.ql-editor .ql-size-huge { + font-size: 2.5em; +} +.ql-editor .ql-direction-rtl { + direction: rtl; + text-align: inherit; +} +.ql-editor .ql-align-center { + text-align: center; +} +.ql-editor .ql-align-justify { + text-align: justify; +} +.ql-editor .ql-align-right { + text-align: right; +} +.ql-editor.ql-blank::before { + content: attr(data-placeholder); + color: var(--grey-400, #AEB3B8); + /* Body 02 */ + font-family: SUIT; + font-size: 18px; + font-style: normal; + font-weight: 500; + line-height: 140%; /* 25.2px */ + left: 15px; + pointer-events: none; + position: absolute; + right: 15px; +} +/* Bold, Italic, Underline, Strike */ +.ql-editor strong{ + font-weight:bold; +} +.ql-editor em{ + font-style: italic; +} +.ql-editor u{ + text-decoration: underline; +} +.ql-editor s{ + text-decoration: line-through; +} +.ql-snow.ql-toolbar:after, +.ql-snow .ql-toolbar:after { + clear: both; + content: ''; + display: table; +} +.ql-snow.ql-toolbar button, +.ql-snow .ql-toolbar button { + background: none; + border: none; + cursor: pointer; + display: inline-block; + float: left; + height: 24px; + padding: 3px 5px; + width: 28px; +} +.ql-snow.ql-toolbar button svg, +.ql-snow .ql-toolbar button svg { + float: left; + height: 100%; +} +.ql-snow.ql-toolbar button:active:hover, +.ql-snow .ql-toolbar button:active:hover { + outline: none; +} +.ql-snow.ql-toolbar input.ql-image[type=file], +.ql-snow .ql-toolbar input.ql-image[type=file] { + display: none; +} +.ql-snow.ql-toolbar button:hover, +.ql-snow .ql-toolbar button:hover, +.ql-snow.ql-toolbar button:focus, +.ql-snow .ql-toolbar button:focus, +.ql-snow.ql-toolbar button.ql-active, +.ql-snow .ql-toolbar button.ql-active, +.ql-snow.ql-toolbar .ql-picker-label:hover, +.ql-snow .ql-toolbar .ql-picker-label:hover, +.ql-snow.ql-toolbar .ql-picker-label.ql-active, +.ql-snow .ql-toolbar .ql-picker-label.ql-active, +.ql-snow.ql-toolbar .ql-picker-item:hover, +.ql-snow .ql-toolbar .ql-picker-item:hover, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected { + color: #3EA2FF; +} +.ql-snow.ql-toolbar button:hover .ql-fill, +.ql-snow .ql-toolbar button:hover .ql-fill, +.ql-snow.ql-toolbar button:focus .ql-fill, +.ql-snow .ql-toolbar button:focus .ql-fill, +.ql-snow.ql-toolbar button.ql-active .ql-fill, +.ql-snow .ql-toolbar button.ql-active .ql-fill, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-fill, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-fill, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-fill, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-fill, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-fill, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-fill, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-fill, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-fill, +.ql-snow.ql-toolbar button:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar button:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar button:focus .ql-stroke.ql-fill, +.ql-snow .ql-toolbar button:focus .ql-stroke.ql-fill, +.ql-snow.ql-toolbar button.ql-active .ql-stroke.ql-fill, +.ql-snow .ql-toolbar button.ql-active .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke.ql-fill, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke.ql-fill { + fill: #06c; +} +.ql-snow.ql-toolbar button:hover .ql-stroke, +.ql-snow .ql-toolbar button:hover .ql-stroke, +.ql-snow.ql-toolbar button:focus .ql-stroke, +.ql-snow .ql-toolbar button:focus .ql-stroke, +.ql-snow.ql-toolbar button.ql-active .ql-stroke, +.ql-snow .ql-toolbar button.ql-active .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke, +.ql-snow.ql-toolbar button:hover .ql-stroke-miter, +.ql-snow .ql-toolbar button:hover .ql-stroke-miter, +.ql-snow.ql-toolbar button:focus .ql-stroke-miter, +.ql-snow .ql-toolbar button:focus .ql-stroke-miter, +.ql-snow.ql-toolbar button.ql-active .ql-stroke-miter, +.ql-snow .ql-toolbar button.ql-active .ql-stroke-miter, +.ql-snow.ql-toolbar .ql-picker-label:hover .ql-stroke-miter, +.ql-snow .ql-toolbar .ql-picker-label:hover .ql-stroke-miter, +.ql-snow.ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter, +.ql-snow .ql-toolbar .ql-picker-label.ql-active .ql-stroke-miter, +.ql-snow.ql-toolbar .ql-picker-item:hover .ql-stroke-miter, +.ql-snow .ql-toolbar .ql-picker-item:hover .ql-stroke-miter, +.ql-snow.ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter, +.ql-snow .ql-toolbar .ql-picker-item.ql-selected .ql-stroke-miter { + stroke: #06c; +} +@media (pointer: coarse) { + .ql-snow.ql-toolbar button:hover:not(.ql-active), + .ql-snow .ql-toolbar button:hover:not(.ql-active) { + color: #444; + } + .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-fill, + .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-fill, + .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill, + .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke.ql-fill { + fill: #444; + } + .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke, + .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke, + .ql-snow.ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter, + .ql-snow .ql-toolbar button:hover:not(.ql-active) .ql-stroke-miter { + stroke: #444; + } +} +.ql-snow { + box-sizing: border-box; +} +.ql-snow * { + box-sizing: border-box; +} +.ql-snow .ql-hidden { + display: none; +} +.ql-snow .ql-out-bottom, +.ql-snow .ql-out-top { + visibility: hidden; +} +.ql-snow .ql-tooltip { + position: absolute; + transform: translateY(10px); +} +.ql-snow .ql-tooltip a { + cursor: pointer; + text-decoration: none; +} +.ql-snow .ql-tooltip.ql-flip { + transform: translateY(-10px); +} +.ql-snow .ql-formats { + display: inline-block; + vertical-align: middle; +} +.ql-snow .ql-formats:after { + clear: both; + content: ''; + display: table; +} +.ql-snow .ql-stroke { + fill: none; + stroke: #444; + stroke-linecap: round; + stroke-linejoin: round; + stroke-width: 2; +} +.ql-snow .ql-stroke-miter { + fill: none; + stroke: #444; + stroke-miterlimit: 10; + stroke-width: 2; +} +.ql-snow .ql-fill, +.ql-snow .ql-stroke.ql-fill { + fill: #444; +} +.ql-snow .ql-empty { + fill: none; +} +.ql-snow .ql-even { + fill-rule: evenodd; +} +.ql-snow .ql-thin, +.ql-snow .ql-stroke.ql-thin { + stroke-width: 1; +} +.ql-snow .ql-transparent { + opacity: 0.4; +} +.ql-snow .ql-direction svg:last-child { + display: none; +} +.ql-snow .ql-direction.ql-active svg:last-child { + display: inline; +} +.ql-snow .ql-direction.ql-active svg:first-child { + display: none; +} +.ql-snow .ql-editor h1 { + font-size: 2em; +} +.ql-snow .ql-editor h2 { + font-size: 1.5em; +} +.ql-snow .ql-editor h3 { + font-size: 1.17em; +} +.ql-snow .ql-editor h4 { + font-size: 1em; +} +.ql-snow .ql-editor h5 { + font-size: 0.83em; +} +.ql-snow .ql-editor h6 { + font-size: 0.67em; +} +.ql-snow .ql-editor a { + text-decoration: underline; +} +.ql-snow .ql-editor blockquote { + border-left: 4px solid #ccc; + margin-bottom: 5px; + margin-top: 5px; + padding-left: 16px; + font-size: 16px; +} +.ql-snow .ql-editor code, +.ql-snow .ql-editor pre { + background-color: #f0f0f0; + border-radius: 3px; +} +.ql-snow .ql-editor pre { + white-space: pre-wrap; + margin-bottom: 5px; + margin-top: 5px; + padding: 5px 10px; +} +.ql-snow .ql-editor code { + font-size: 85%; + padding: 2px 4px; +} +.ql-snow .ql-editor pre.ql-syntax { + background-color: #23241f; + color: #f8f8f2; + overflow: visible; +} +.ql-snow .ql-editor img { + max-width: 100%; +} +.ql-snow .ql-picker { + color: #444; + display: inline-block; + float: left; + font-size: 14px; + font-weight: 500; + height: 24px; + position: relative; + vertical-align: middle; +} +.ql-snow .ql-picker-label { + cursor: pointer; + display: inline-block; + height: 100%; + padding-left: 8px; + padding-right: 2px; + position: relative; + width: 100%; +} +.ql-snow .ql-picker-label::before { + display: inline-block; + line-height: 22px; +} +.ql-snow .ql-picker-options { + background-color: #fff; + display: none; + min-width: 100%; + padding: 4px 8px; + position: absolute; + white-space: nowrap; +} +.ql-snow .ql-picker-options .ql-picker-item { + cursor: pointer; + display: block; + padding-bottom: 5px; + padding-top: 5px; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label { + color: #ccc; + z-index: 2; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-fill { + fill: #ccc; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-label .ql-stroke { + stroke: #ccc; +} +.ql-snow .ql-picker.ql-expanded .ql-picker-options { + display: block; + margin-top: -1px; + top: 100%; + z-index: 1; +} +.ql-snow .ql-color-picker, +.ql-snow .ql-icon-picker { + width: 28px; +} +.ql-snow .ql-color-picker .ql-picker-label, +.ql-snow .ql-icon-picker .ql-picker-label { + padding: 2px 4px; +} +.ql-snow .ql-color-picker .ql-picker-label svg, +.ql-snow .ql-icon-picker .ql-picker-label svg { + right: 4px; +} +.ql-snow .ql-icon-picker .ql-picker-options { + padding: 4px 0px; +} +.ql-snow .ql-icon-picker .ql-picker-item { + height: 24px; + width: 24px; + padding: 2px 4px; +} +.ql-snow .ql-color-picker .ql-picker-options { + padding: 3px 5px; + width: 152px; +} +.ql-snow .ql-color-picker .ql-picker-item { + border: 1px solid transparent; + float: left; + height: 16px; + margin: 2px; + padding: 0px; + width: 16px; +} +.ql-snow .ql-picker:not(.ql-color-picker):not(.ql-icon-picker) svg { + position: absolute; + margin-top: -9px; + right: 0; + top: 50%; + width: 18px; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-font .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-size .ql-picker-label[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-label]:not([data-label=''])::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-label]:not([data-label=''])::before { + content: attr(data-label); +} +.ql-snow .ql-picker.ql-header { + width: 98px; +} +.ql-snow .ql-picker.ql-header .ql-picker-label::before, +.ql-snow .ql-picker.ql-header .ql-picker-item::before { + content: 'Normal'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { + content: 'Heading 1'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { + content: 'Heading 2'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { + content: 'Heading 3'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { + content: 'Heading 4'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { + content: 'Heading 5'; +} +.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before, +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { + content: 'Heading 6'; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before { + font-size: 2em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before { + font-size: 1.5em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before { + font-size: 1.17em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before { + font-size: 1em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before { + font-size: 0.83em; +} +.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before { + font-size: 0.67em; +} +.ql-snow .ql-picker.ql-font { + width: 108px; +} +.ql-snow .ql-picker.ql-font .ql-picker-label::before, +.ql-snow .ql-picker.ql-font .ql-picker-item::before { + content: 'Sans Serif'; +} +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=serif]::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { + content: 'Serif'; +} +.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=monospace]::before, +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { + content: 'Monospace'; +} +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=serif]::before { + font-family: Georgia, Times New Roman, serif; +} +.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=monospace]::before { + font-family: Monaco, Courier New, monospace; +} +.ql-snow .ql-picker.ql-size { + width: 98px; +} +.ql-snow .ql-picker.ql-size .ql-picker-label::before, +.ql-snow .ql-picker.ql-size .ql-picker-item::before { + content: 'Normal'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=small]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { + content: 'Small'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=large]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { + content: 'Large'; +} +.ql-snow .ql-picker.ql-size .ql-picker-label[data-value=huge]::before, +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { + content: 'Huge'; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=small]::before { + font-size: 10px; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=large]::before { + font-size: 18px; +} +.ql-snow .ql-picker.ql-size .ql-picker-item[data-value=huge]::before { + font-size: 32px; +} +.ql-snow .ql-color-picker.ql-background .ql-picker-item { + background-color: #fff; +} +.ql-snow .ql-color-picker.ql-color .ql-picker-item { + background-color: #000; +} +.ql-toolbar.ql-snow { + display: flex; + align-items: center; + + border: 1px solid #E3E7ED; + box-sizing: border-box; + font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; + padding: 0 27px; + border-top-left-radius: 20px; + border-top-right-radius: 20px; + background: var(--background, #F6F6F6); + height: 64px; +} +.ql-toolbar.ql-snow .ql-formats { + margin-right: 15px; +} +.ql-toolbar.ql-snow .ql-picker-label { + border: 1px solid transparent; +} +.ql-toolbar.ql-snow .ql-picker-options { + border: 1px solid transparent; + box-shadow: rgba(0,0,0,0.2) 0 2px 8px; +} +.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-label { + border-color: #ccc; +} +.ql-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options { + border-color: #ccc; +} +.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item.ql-selected, +.ql-toolbar.ql-snow .ql-color-picker .ql-picker-item:hover { + border-color: #000; +} +.ql-toolbar.ql-snow + .ql-container.ql-snow { + border-top: 0px; +} +.ql-snow .ql-tooltip { + background-color: #fff; + border: 1px solid #ccc; + box-shadow: 0px 0px 5px #ddd; + color: #444; + padding: 5px 12px; + white-space: nowrap; +} +.ql-snow .ql-tooltip::before { + content: "Visit URL:"; + line-height: 26px; + margin-right: 8px; +} +.ql-snow .ql-tooltip input[type=text] { + display: none; + border: 1px solid #ccc; + font-size: 13px; + height: 26px; + margin: 0px; + padding: 3px 5px; + width: 170px; +} +.ql-snow .ql-tooltip a.ql-preview { + display: inline-block; + max-width: 200px; + overflow-x: hidden; + text-overflow: ellipsis; + vertical-align: top; +} +.ql-snow .ql-tooltip a.ql-action::after { + border-right: 1px solid #ccc; + content: 'Edit'; + margin-left: 16px; + padding-right: 8px; +} +.ql-snow .ql-tooltip a.ql-remove::before { + content: 'Remove'; + margin-left: 8px; +} +.ql-snow .ql-tooltip a { + line-height: 26px; +} +.ql-snow .ql-tooltip.ql-editing a.ql-preview, +.ql-snow .ql-tooltip.ql-editing a.ql-remove { + display: none; +} +.ql-snow .ql-tooltip.ql-editing input[type=text] { + display: inline-block; +} +.ql-snow .ql-tooltip.ql-editing a.ql-action::after { + border-right: 0px; + content: 'Save'; + padding-right: 0px; +} +.ql-snow .ql-tooltip[data-mode=link]::before { + content: "Enter link:"; +} +.ql-snow .ql-tooltip[data-mode=formula]::before { + content: "Enter formula:"; +} +.ql-snow .ql-tooltip[data-mode=video]::before { + content: "Enter video:"; +} +.ql-snow a { + color: #06c; +} +.ql-container.ql-snow { + border: 1px solid #E3E7ED; + height: 556px; +}