1st commit

This commit is contained in:
2025-07-01 11:09:51 +02:00
commit 2d3e33d643
787 changed files with 185055 additions and 0 deletions

View File

@@ -0,0 +1,112 @@
<!DOCTYPE html>
<html lang="fr" data-theme="apxtri" class="h-full bg-neutral">
<head>
<meta charset="utf-8" />
<title>Admin Template</title>
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<meta
content="saas, apxtri"
name="keywords"
/>
<meta
content="A saas solution that you can host at home to master your data"
name="description"
/>
<link data-wco="favicon" href="static/img/icons/iconbgdark.png" rel="icon" />
<link href="static/css/twstyle.css" rel="stylesheet" />
<script>
/**
* Read apx.js to know more
*/
const apxtri = {
headers: {
xtrkversion: 1,
xtribe: "apxtri",
xapp: "admin",
xlang: "fr",
xalias: "anonymous",
xhash: "anonymous",
xprofils:["anonymous"],
xdays: 0,
},
pagename: "admindata",
pageauth: "apxid",
allowedprofils:["anonymous"],
searchfunction:"adminsearch", // must exist a function call apx.adminsearch(search) that return a relevant result check example
version:0
};
</script>
<script src="/apxtri/node_modules/axios/dist/axios.min.js"></script>
<script src="/apxtri/node_modules/dayjs/dayjs.min.js"></script>
<script src="/apxtri/node_modules/openpgp/dist/openpgp.min.js"></script>
<script src="/apxtri/node_modules/mustache/mustache.min.js"></script>
<script src="/apxtri/Checkjson.js"></script>
<script src="/api/apxtri/wwws/getwco/apx.js?wcotribe=apxtri&tribe=apxtri&xapp=admin&pagename=admindata&code=enjoy"></script>
<script src="/api/apxtri/wwws/getwco/adminskull.js?wcotribe=apxtri&tribe=apxtri&xapp=admin&pagename=admindata&code=enjoy"></script>
<script src="static/js/adminsearch.js"></script>
</head>
<body class="bg-gray-100">
<div class="flex min-h-screen">
<!-- Vertical Navigation Menu -->
<!--button onclick="apx.adminskull.togglesidebarmobile(this)" class="sm:hidden fixed top-4 left-4 z-50 p-2 bg-base-200 rounded-lg shadow">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7" />
</svg>
</button-->
<nav id="sidebar" class="bg-neutral-800 text-white fixed sm:relative sm:w-64 w-0 transform transition-all duration-300 ease-in-out -translate-x-full sm:translate-x-0 p-4 shadow-lg z-40 overflow-hidden hidden flex flex-col h-screen">
<!--nav id="sidebar" class="hidden sm:block bg-neutral-800 text-white w-64 h-screen flex flex-col shadow-lg transition-width"-->
<!-- User Profile Section -->
<div class="p-4">
<div class="flex items-center justify-between"> <!-- Ajout de justify-between pour aligner la croix à droite -->
<!-- Image et texte -->
<div class="flex items-center">
<img data-wco="favicon" src="static/img/icons/iconbglight.png" class="rounded-full h-9 w-9 mr-3" alt="apXtri">
<div>
<h2 data-wco="companyname" class="text-base font-semibold">apXtri</h2>
<p data-wco="claim" class="text-sm text-gray-400">L'unique et sa propriété</p>
</div>
</div>
<!-- Icône de croix (fermeture) -->
<button onclick="apx.adminskull.togglesidebarmobile(this)" class="text-gray-400 hover:text-white sm:hidden">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
<!-- Menu Links Section -->
</nav>
<!-- Main Content Area -->
<div class="flex-1 bg-gray-100">
<!-- Horizontal Navigation Bar -->
<header class="bg-white shadow-md p-4">
<div id="headnav" class="flex items-center justify-between">
</div>
</header>
<div id="maincontent" class=""> Contenu of id=maincontent</div>
<div id="searchcontent" class=" hidden flex flex-col border border-gray-200 rounded-lg p-4">
<!-- Ligne avec la flèche de retour -->
<div class="flex justify-between items-center mb-4">
<h2 id="searchtitle" class="text-lg font-semibold">Résultat sur: </h2>
<!-- Flèche de retour (icône DaisyUI) -->
<button class="btn btn-circle btn-sm btn-ghost" onclick="document.getElementById('searchcontent').classList.add('hidden');document.getElementById('maincontent').classList.remove('hidden');">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
</button>
</div>
<!-- Div de contenu -->
<div id="searchresults" class="bg-base-200 text-base-content p-4 rounded-lg">
<p>Show search result here...</p>
</div>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="fr" data-theme="apxtridark" class="h-full bg-base-200 text-neutral-content ">
<head>
<meta charset="utf-8" />
<title>Authentification</title>
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<meta
content="L'unique et sa propriété, authentification, apxtri, cle public, cle privée"
name="keywords"
/>
<meta
content="Porte d'entrée dans l'univers libre d'apXtri, là où vous pouvez être l'Unique et sa propriété."
name="description"
/>
<link data-wco="favicon" href="static/img/icons/iconbgdark.png" rel="icon" />
<!--script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script-->
<link href="static/css/output.css" rel="stylesheet" />
<script>
/**
* Read apx.js to know more
*/
const apxtri = {
headers: {
xtrkversion: 1,
xtribe: "apxtri",
xapp: "admin",
xlang: "fr",
xalias: "anonymous",
xhash: "anonymous",
xprofils:["anonymous"],
xdays: 0,
xuuid:0
},
pagename: "apxid",
pageauth: "apxid",
wcoobserver:true,
allowedprofils:["anonymous"],
version:0
};
</script>
<script src="/apxtri/node_modules/axios/dist/axios.min.js"></script>
<script src="/apxtri/node_modules/dayjs/dayjs.min.js"></script>
<script src="/apxtri/node_modules/openpgp/dist/openpgp.min.js"></script>
<script src="/apxtri/node_modules/mustache/mustache.min.js"></script>
<script src="/apxtri/Checkjson.js"></script>
<script src="/api/apxtri/wwws/getwco/apx.js?wcotribe=apxtri&tribe=apxtri&xapp=admin&pagename=apxid&code=enjoy"></script>
<script src="/api/apxtri/wwws/getwco/simplemobnav.js?wcotribe=apxtri&tribe=apxtri&xapp=admin&pagename=apxid&code=enjoy&tagid=authentification"></script>
<script src="/api/apxtri/wwws/getwco/apxauth.js?wcotribe=apxtri&tribe=apxtri&xapp=admin&pagename=apxid&code=enjoy&tagid=signature"></script>
</head>
<body class="h-full">
<div class="flex items-center justify-center min-h-screen px-4">
<div
id="authentification"
wco-name="simplemobnav"
class="bg-base-100 min-h-screen w-full p-4 text-center">
</div>
<!--div wco-name="chatroom" class="hidden min-h-full flex-col justify-center px-6 py-12 lg:px-8">
</div-->
</div>
</body>
</html>

View File

@@ -0,0 +1,7 @@
<div class="mb-4 p-4 bg-green-50 rounded-lg shadow">
<p class="text-green-600">Currently active</p>
<p class="text-gray-800">Job Ad Title {{jobAdNumber}}</p>
<p class="text-gray-500">Expiry Date</p>
<p class="text-gray-800">DD month YYYY (X days remaining)</p>
</div>

View File

@@ -0,0 +1,26 @@
.attention-message {
text-align: center;
}
.attention-message-heading,
.attention-message-subheading {
color: #F04438;
font-family: 'Inter', sans-serif;
font-size: 18px;
font-style: normal;
font-weight: 700;
line-height: 28px;
}
.attention-message-subheading {
margin-bottom: 16px;
}
.attention-message-body {
color: #18191E;
font-family: 'Inter', sans-serif;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
}

View File

@@ -0,0 +1,5 @@
<div class="attention-message p-4">
<p class="attention-message-heading">Attention:</p>
<p class="attention-message-subheading">You currently have X job ads active.</p>
<p class="attention-message-body">When your plan expires, all active job ads will be removed and candidates notified the job has been canceled lorem ipsum.</p>
</div>

View File

@@ -0,0 +1,28 @@
.button-container {
display: flex;
width: 325px;
height: 48px;
justify-content: center;
align-items: center;
background-color: var(--app-button-background, #000);
border-radius: 4px;
}
.button-label {
color: var(--_app-global-grayscale-50, #F9FAFB);
text-align: center;
font-family: 'Inter', sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 900;
line-height: 20px;
text-transform: uppercase;
margin-right: 8px;
}
.button-icon {
width: var(--Spacing-Link-Below-Textfield, 18px);
height: var(--Spacing-Link-Below-Textfield, 18px);
flex-shrink: 0;
}

View File

@@ -0,0 +1,3 @@
<button class="btn w-full flex justify-between items-center mb-2" id="button-element">
<span id="button-text">BUTTON TEXT</span>
</button>

View File

@@ -0,0 +1,6 @@
function initializeButton(buttonText, buttonAction) {
const buttonElement = document.getElementById('button-element');
buttonElement.innerText = buttonText;
buttonElement.addEventListener('click', buttonAction);
}

View File

@@ -0,0 +1,16 @@
<div class="job-ad-detail p-4 bg-white rounded-lg shadow mb-4">
<p class="text-green-500">Currently active</p>
<p class="text-gray-800">Job Ad Title #1</p>
<p class="text-gray-600">Expiry Date</p>
<p class="text-gray-800">DD month YYYY (X days remaining)</p>
</div>
<div class="job-ad-detail p-4 bg-white rounded-lg shadow mb-4">
<p class="text-green-500">Currently active</p>
<p class="text-gray-800">Job Ad Title #2</p>
<p class="text-gray-600">Expiry Date</p>
<p class="text-gray-800">DD month YYYY (X days remaining)</p>
</div>
<div class="job-ad-detail p-4 bg-white rounded-lg shadow mb-4">
<p class="text-gray-500">Ready to be used / Not active</p>
<p class="text-gray-800">Job Ad Title #3</p>
</div>

View File

@@ -0,0 +1,19 @@
function showExtraJobAdsTab() {
document.getElementById('extra-job-ads-content').classList.remove('hidden');
document.getElementById('extra-job-ads-tab').classList.add('custom-tab-active');
document.getElementById('extra-job-ads-tab').classList.remove('custom-tab-inactive');
loadComponent('buttons-container', 'components/Button.html', () => {
document.getElementById('button-text').innerText = 'GET EXTRA JOB ADS';
const buttonElement = document.getElementById('button-element');
buttonElement.classList.add('bg-black', 'text-white');
buttonElement.innerHTML += `
<svg class="h-6 w-6 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
`;
});
}

View File

@@ -0,0 +1,7 @@
<div class="flex justify-start mb-4">
<button class="btn btn-circle btn-outline" id="close-button">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
</svg>
</button>
</div>

View File

@@ -0,0 +1,5 @@
<div class="mb-4 p-4 bg-gray-50 rounded-lg shadow">
<p class="text-gray-600">Ready to be used / Not active</p>
<p class="text-gray-800">Job Ad Title {{jobAdNumber}}</p>
</div>

View File

@@ -0,0 +1,7 @@
<div class="mb-4 p-4 bg-gray-50 rounded-lg shadow">
<p class="text-gray-500" id="job-ad-status"></p>
<p class="text-gray-800" id="job-ad-title"></p>
<p class="text-gray-600" id="job-ad-expiry-label"></p>
<p class="text-gray-800" id="job-ad-expiry"></p>
</div>

View File

@@ -0,0 +1,53 @@
.job-ad-detail {
display: flex;
flex-direction: column;
padding: 16px;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
margin-bottom: 16px;
}
.active-job-ad {
background-color: #f9fafb;
}
.inactive-job-ad {
background-color: #f3f4f6;
}
.job-ad-title {
font-family: 'Inter', sans-serif;
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 24px;
color: var(--app-text-stroke-text-stroke-day, #18191E);
margin-bottom: 16px;
}
.status {
font-family: 'Inter', sans-serif;
font-weight: 600;
font-size: 14px;
line-height: 20px;
margin-bottom: 8px;
}
.job-title {
font-family: 'Inter', sans-serif;
font-weight: 400;
font-size: 14px;
line-height: 20px;
margin-top: 8px;
margin-bottom: 16px;
}
.expiry-label,
.expiry-date {
font-family: 'Inter', sans-serif;
font-weight: 400;
font-size: 14px;
line-height: 20px;
margin-top: 8px;
}

View File

@@ -0,0 +1,72 @@
function generateJobAds(activeCount, inactiveCount) {
const container = document.getElementById('extra-job-ads-content');
container.innerHTML = ''; // Clear existing content
// Update the tab text with the total number of job ads
const totalJobAds = activeCount + inactiveCount;
const extraJobAdsTab = document.getElementById('extra-job-ads-tab');
extraJobAdsTab.textContent = `Extra job ads (${totalJobAds})`;
// Generate active job ads
for (let i = 1; i <= activeCount; i++) {
const activeAdContainer = document.createElement('div');
activeAdContainer.className = 'job-ad-container mb-4';
const activeAdTitle = document.createElement('p');
activeAdTitle.className = 'job-ad-title text-gray-800';
activeAdTitle.textContent = `Extra job ad #${i} (currently in use)`;
const activeAd = document.createElement('div');
activeAd.className = 'job-ad-detail active-job-ad p-4 bg-white rounded-lg shadow';
activeAd.innerHTML = `
<p class="text-green-500 status">Currently active</p>
<p class="text-gray-800 job-title">&lt;Job ad title&gt;</p>
<p class="text-gray-600 expiry-label">Expiry Date</p>
<p class="text-gray-800 expiry-date">DD month YYYY (X days remaining)</p>
`;
activeAdContainer.appendChild(activeAdTitle);
activeAdContainer.appendChild(activeAd);
container.appendChild(activeAdContainer);
}
// Generate inactive job ads
for (let i = 1; i <= inactiveCount; i++) {
const inactiveAdContainer = document.createElement('div');
inactiveAdContainer.className = 'job-ad-container mb-4';
const inactiveAdTitle = document.createElement('p');
inactiveAdTitle.className = 'job-ad-title text-gray-800';
inactiveAdTitle.textContent = `Extra job ad #${i + activeCount}`;
const inactiveAd = document.createElement('div');
inactiveAd.className = 'job-ad-detail inactive-job-ad p-4 bg-white rounded-lg shadow';
inactiveAd.innerHTML = `
<p class="text-gray-500 status">Ready to be used / Not active</p>
`;
inactiveAdContainer.appendChild(inactiveAdTitle);
inactiveAdContainer.appendChild(inactiveAd);
container.appendChild(inactiveAdContainer);
}
}
function showExtraJobAdsTab() {
document.getElementById('extra-job-ads-content').classList.remove('hidden');
document.getElementById('extra-job-ads-tab').classList.add('custom-tab-active');
document.getElementById('extra-job-ads-tab').classList.remove('custom-tab-inactive');
loadComponent('buttons-container', 'components/Button.html', () => {
document.getElementById('button-text').innerText = 'GET EXTRA JOB ADS';
const buttonElement = document.getElementById('button-element');
buttonElement.classList.add('bg-black', 'text-white');
buttonElement.innerHTML += `
<svg class="h-6 w-6 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
`;
});
// Generate job ads dynamically
generateJobAds(2, 1);
}

View File

@@ -0,0 +1,7 @@
<div id="extra-job-ads-content" class="p-4 bg-white rounded-lg shadow mb-4">
<h3 class="text-xl font-bold mb-4">You don't have any extra job ads at the moment lorem ipsum</h3>
<p class="text-gray-600 mb-4">Generic description talking about the benefits of extra job ads lorem ipsum</p>
<div class="w-full h-48 bg-gray-200 flex items-center justify-center rounded-lg mb-4">
<p class="text-gray-500">empty state illustration</p>
</div>
</div>

View File

@@ -0,0 +1,42 @@
.no-subscription-container {
width: 100%;
max-width: 600px;
margin: 0 auto;
padding: 20px;
background-color: white;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.no-subscription-container h3 {
color: var(--app-text-stroke-text-stroke-day, #18191E);
text-align: center;
font-family: 'Montserrat', sans-serif;
font-size: 24px;
font-style: normal;
font-weight: 700;
line-height: 32px;
margin-bottom: 16px;
}
.no-subscription-container p {
color: var(--app-text-stroke-text-stroke-day, #18191E);
text-align: center;
font-family: 'Inter', sans-serif;
font-size: 16px;
font-style: normal;
font-weight: 600;
line-height: 24px;
margin-bottom: 16px;
}
.no-subscription-illustration {
width: var(--Chart-Module-Width, 325px);
height: 260px;
background-color: #e5e7eb;
display: flex;
align-items: center;
justify-content: center;
border-radius: 8px;
margin: 0 auto;
}

View File

@@ -0,0 +1,7 @@
<div id="no-subscription-content" class="no-subscription-container">
<h3 id="no-subscription-title">You don't have any extra job ads at the moment lorem ipsum</h3>
<p id="no-subscription-description">Generic description talking about the benefits of extra job ads lorem pisum</p>
<div class="no-subscription-illustration">
<img id="no-subscription-image" src="" alt="Illustration" class="w-full h-full object-cover">
</div>
</div>

View File

@@ -0,0 +1,9 @@
body {
font-family: var(--font-family-inter);
}
.content-container {
background-color: #f3f4f6;
padding-bottom: 4rem;
}

View File

@@ -0,0 +1,4 @@
<div id="plan-header" class="mb-4">
<h2 class="text-xl font-semibold text-gray-900">Your plan: <span class="text-gray-600">&lt;Plan name from stripe&gt;</span></h2>
</div>
<div id="plan-detail-items" class="space-y-4 bg-white p-6 rounded-lg shadow"></div>

View File

@@ -0,0 +1,6 @@
<!-- PlanDetailItem.html -->
<div class="mb-4 p-4 bg-gray-50 rounded-lg shadow">
<p class="text-gray-500">{{label}}</p>
<p class="text-gray-800">{{value}}</p>
</div>

View File

@@ -0,0 +1,36 @@
#plan-detail-items {
font-family: 'Inter', sans-serif;
}
.plan-detail-item {
display: flex;
flex-direction: column;
width: 345px;
padding: 0px 8px 9px 0px;
align-items: flex-start;
gap: 2px;
margin-bottom: 9px;
border-bottom: 1px solid #e5e7eb;
}
.plan-detail-item:last-child {
border-bottom: none;
}
.plan-detail-label {
color: var(--app-text-stroke-text-stroke-day, #18191E);
font-family: 'Inter', sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 600;
line-height: 20px;
}
.plan-detail-value {
color: var(--app-text-stroke-text-stroke-day, #18191E);
font-family: 'Inter', sans-serif;
font-size: 13px;
font-style: normal;
font-weight: 400;
line-height: 16px;
}

View File

@@ -0,0 +1,22 @@
<div id="subscriptions-content" class="p-4 bg-white rounded-lg shadow mb-4">
<h3 class="text-xl font-bold mb-4">Your plan: <Plan name from stripe></h3>
<!-- Description -->
<div id="plan-detail-description"></div>
<!-- Price per month -->
<div id="plan-detail-price"></div>
<!-- Active job ads -->
<div id="plan-detail-ads"></div>
<!-- Renewal date -->
<div id="plan-detail-renewal"></div>
</div>
<!-- Action Buttons for Subscriptions Tab -->
<div id="subscriptions-buttons" class="sticky-footer">
<div id="update-plan-button"></div>
<a href="#" class="block text-center text-red-600" id="cancel-subscription-button">Cancel subscription</a>
</div>

View File

@@ -0,0 +1,56 @@
function showSubscriptionTab(planCanceled) {
document.getElementById('subscriptions-content').classList.remove('hidden');
document.getElementById('subscriptions-tab').classList.add('custom-tab-active');
document.getElementById('subscriptions-tab').classList.remove('custom-tab-inactive');
loadComponent('buttons-container', 'components/Button.html', () => {
const buttonText = planCanceled ? 'RE-SUBSCRIBE' : 'UPDATE PLAN';
document.getElementById('button-text').innerText = buttonText;
const buttonElement = document.getElementById('button-element');
buttonElement.classList.add('bg-black', 'text-white');
buttonElement.innerHTML += `
<svg class="h-6 w-6 ml-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
</svg>
`;
if (!planCanceled) {
const buttonsContainer = document.getElementById('buttons-container');
buttonsContainer.innerHTML += '<a href="#" class="block text-center text-red-600">Cancel subscription</a>';
}
});
// Plan details
const planDetails = [
{ label: 'Description', value: 'Plan description from stripe lorem ipsum', className: 'text-gray-800', labelClassName: 'text-gray-500' },
{ label: 'Price per month', value: 'XX.XX € / month', className: 'text-gray-800', labelClassName: 'text-gray-500' },
{ label: 'Active job ads', value: 'X / Total N', className: planCanceled ? 'text-red-500' : 'text-gray-800', labelClassName: planCanceled ? 'text-red-500' : 'text-gray-500' },
{ label: planCanceled ? 'Expiry date' : 'Renewal date', value: 'DD month YYYY', additionalText: planCanceled ? '(X days remaining)' : '', className: planCanceled ? 'text-red-500' : 'text-gray-800', labelClassName: planCanceled ? 'text-red-500' : 'text-gray-500' },
];
const planDetailItemsContainer = document.getElementById('plan-detail-items');
planDetailItemsContainer.innerHTML = '';
planDetails.forEach(detail => {
loadComponent(null, 'components/PlanDetailItem.html', () => {
const item = document.createElement('div');
item.className = 'plan-detail-item';
item.innerHTML = `
<p class="${detail.labelClassName}">${detail.label}</p>
<p class="${detail.className}">${detail.value} ${detail.additionalText || ''}</p>
`;
planDetailItemsContainer.appendChild(item);
});
});
if (planCanceled) {
const attentionMessageContainer = document.createElement('div');
attentionMessageContainer.id = 'attention-message-container';
document.getElementById('subscriptions-content').appendChild(attentionMessageContainer);
loadComponent('attention-message-container', 'components/AttentionMessage.html');
} else {
const attentionMessageContainer = document.getElementById('attention-message-container');
if (attentionMessageContainer) {
attentionMessageContainer.innerHTML = '';
}
}
}

View File

@@ -0,0 +1,4 @@
<div class="custom-tabs">
<div id="subscriptions-tab" class="custom-tab custom-tab-active" onclick="showTab('subscriptions')">Subscriptions</div>
<div id="extra-job-ads-tab" class="custom-tab custom-tab-inactive" onclick="showTab('extra-job-ads')">Extra job ads (0)</div>
</div>

View File

@@ -0,0 +1,48 @@
function loadComponent(containerId, filePath, callback) {
fetch(filePath)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.text();
})
.then(data => {
if (containerId) {
document.getElementById(containerId).innerHTML = data;
}
if (callback) callback();
})
.catch(error => console.error('Error loading component:', error));
}
function showTab(tab) {
document.getElementById('subscriptions-content').classList.add('hidden');
document.getElementById('extra-job-ads-content').classList.add('hidden');
document.getElementById('subscriptions-tab').classList.remove('custom-tab-active');
document.getElementById('extra-job-ads-tab').classList.remove('custom-tab-active');
document.getElementById('subscriptions-tab').classList.add('custom-tab-inactive');
document.getElementById('extra-job-ads-tab').classList.add('custom-tab-inactive');
document.getElementById('buttons-container').innerHTML = '';
if (tab === 'subscriptions') {
const planCanceled = false; // Set true or false
showSubscriptionTab(planCanceled);
} else if (tab === 'extra-job-ads') {
showExtraJobAdsTab();
}
}
document.addEventListener("DOMContentLoaded", () => {
loadComponent('header-container', 'components/Header.html');
loadComponent('tabs-container', 'components/Tabs.html');
loadComponent('subscriptions-content', 'components/PlanDetail.html');
loadComponent('extra-job-ads-content', 'components/ExtraJobAds.html', () => {
generateJobAds(2, 1); //Active-Inactive Jobads
});
loadComponent('buttons-container', 'components/Button.html', () => {
showTab('subscriptions');
});
});

View File

@@ -0,0 +1,71 @@
function loadComponent(containerId, filePath, callback) {
fetch(filePath)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.text();
})
.then(data => {
if (containerId) {
document.getElementById(containerId).innerHTML = data;
}
if (callback) callback();
})
.catch(error => console.error('Error loading component:', error));
}
function showTab(tabsConfig, activeTab) {
// Hide all content sections and reset tab classes
tabsConfig.forEach(tab => {
document.getElementById(tab.contentId).classList.add('hidden');
document.getElementById(tab.tabId).classList.remove('custom-tab-active');
document.getElementById(tab.tabId).classList.add('custom-tab-inactive');
});
// Show the selected content section and activate the tab
const activeConfig = tabsConfig.find(tab => tab.name === activeTab);
document.getElementById(activeConfig.contentId).classList.remove('hidden');
document.getElementById(activeConfig.tabId).classList.add('custom-tab-active');
document.getElementById(activeConfig.tabId).classList.remove('custom-tab-inactive');
// Load buttons for the active tab
document.getElementById('buttons-container').innerHTML = '';
loadComponent('buttons-container', activeConfig.buttonFile, () => {
document.getElementById('button-text').innerText = activeConfig.buttonText;
const buttonElement = document.getElementById('button-element');
buttonElement.classList.add('bg-black', 'text-white');
buttonElement.innerHTML += activeConfig.buttonIcon;
});
// Update content based on the active tab
if (activeTab === 'subscriptions') {
updateNoSubscriptionContent('You are not subscribed to any plan lorem ipsum dolor sit amet', 'Generic description talking about the benefits of subscribing lorem ipsum', 'path/to/subscription-illustration.png');
} else if (activeTab === 'extra-job-ads') {
updateNoSubscriptionContent('You don\'t have any extra job ads at the moment lorem ipsum', 'Generic description talking about the benefits of extra job ads lorem pisum', 'path/to/extra-job-ads-illustration.png');
}
}
function initializePage(tabsConfig) {
document.addEventListener("DOMContentLoaded", () => {
loadComponent('header-container', 'components/Header.html');
loadComponent('tabs-container', 'components/Tabs.html', () => {
tabsConfig.forEach(tab => {
document.getElementById(tab.tabId).addEventListener('click', () => showTab(tabsConfig, tab.name));
});
});
tabsConfig.forEach(tab => {
loadComponent(tab.contentId, tab.contentFile);
});
loadComponent('buttons-container', 'components/Button.html', () => {
// Show the first tab by default
showTab(tabsConfig, tabsConfig[0].name);
});
});
}
function updateNoSubscriptionContent(title, description, imagePath) {
document.getElementById('no-subscription-title').innerText = title;
document.getElementById('no-subscription-description').innerText = description;
document.getElementById('no-subscription-image').src = imagePath;
}

View File

@@ -0,0 +1,4 @@
<p id="caption" class="mt-2 text-sm text-gray-500">
This is a descriptive caption for the media.
</p>

View File

@@ -0,0 +1,46 @@
.carousel {
display: flex;
gap: 16px;
overflow-x: scroll;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
padding: 10px;
}
.carousel-item {
width: 420px;
height: 544px;
flex-shrink: 0;
scroll-snap-align: start;
display: flex;
flex-direction: column;
}
.carousel-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
.carousel-item .caption {
margin-top: 8px;
text-align: center;
font-size: 14px;
color: #555;
}
@media (max-width: 640px) {
.carousel {
gap: 8px;
padding: 8px;
}
.carousel-item {
width: 250px;
height: 320px;
}
.carousel-item .caption {
font-size: 12px;
}
}

View File

@@ -0,0 +1,33 @@
document.addEventListener("DOMContentLoaded", function () {
const carouselContainer = document.getElementById('carousel-container');
const mediaItems = Array(10).fill({
type: 'image',
src: 'https://s3-alpha-sig.figma.com/img/37a7/42fb/1daabd5424c6093ca79a6d502b3b84ef?Expires=1724630400&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=FgQK8BhmZm52syueYHL8d33N9v48-lePOhb~KQgE528f-GZn8a8HXap5OvWlCdKaf2nZLlFvmgWgpnuz7iekJqEAS95CknKbniYODvBDOGMVIcHrU7YthPZ~YqZSE7pEANVBVEwkB9-1zJ77gT9uEMryjd-xb44NjnBhfLPkP4B9qlqkbuehRRhLGPBnYA9q3PHpf5ocx7j0~xAbomT~EFX2bzwBu70gKN0qTFVRy8uNu8USYah2YotQH58ChxcEPokhPxENAdNCWeDodsWVFrldbeU0CgVzCrn3MLYu9Ep96r7tjAvKfgQQqC6eORHyM-citVFu1DlJx8-CUN26RQ__',
alt: 'Image with Caption'
});
const renderCarousel = () => {
mediaItems.forEach((item, index) => {
const halfWidthClass = index === 2 ? 'half-width' : '';
const captionText = `Optional image caption lorem ipsum dolor sit amet, consectetur adipiscing elit lorem ipsum`;
carouselContainer.innerHTML += `
<div class="carousel-item ${halfWidthClass}">
${renderMedia(item)}
<div class="caption">${captionText}</div>
</div>
`;
});
};
const renderMedia = (item) => {
if (item.type === 'image') {
return `<img src="${item.src}" alt="${item.alt}">`;
} else if (item.type === 'video') {
return `<video src="${item.src}" controls class="w-full h-auto"></video>`;
}
return '';
};
renderCarousel();
});

View File

@@ -0,0 +1,77 @@
.checkbox-container {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
width: 130px;
}
.checkbox-input {
appearance: none;
border: 2px solid #0DC3FF;
border-radius: 4px;
width: 87px;
height: 20px;
display: flex;
align-items: flex-start;
gap: var(--Input-Element-Radius-CTA-M, 12px);
cursor: pointer;
position: relative;
flex-shrink: 0;
transition: width 0.3s ease, height 0.3s ease;
}
.checkbox-input:checked {
background-color: #0DC3FF;
width: var(--Icon-Sizes-Input, 20px);
height: var(--Icon-Sizes-Input, 20px);
flex-shrink: 0;
}
.checkbox-input:checked::before {
content: '✔';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
}
.checkbox-label {
display: flex;
align-items: center;
cursor: pointer;
flex: 1 0 0;
color: var(--app-input-text-label-day, #1E2024);
font-family: Inter, sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 20px;
}
.checkbox-icon {
margin-right: 0.5rem;
}
.checkbox-label-left {
display: flex;
align-items: center;
justify-content: flex-start;
}
.checkbox-label-left .checkbox-input {
order: 1;
margin-right: auto;
}
.checkbox-label-right {
display: flex;
align-items: center;
justify-content: flex-end;
}
.checkbox-label-right .checkbox-input {
order: 2;
margin-left: auto;
}

View File

@@ -0,0 +1,39 @@
<div class="checkbox-component">
<!-- Horizontal Checkbox with Label and Icon -->
<div class="checkbox-container">
<input type="checkbox" id="checkbox1" class="checkbox checkbox-primary">
<label for="checkbox1" class="checkbox-label">Label with Icon</label>
<span class="checkbox-icon">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11.41l-3.3 3.29-1.29-1.29a1 1 0 10-1.42 1.42l2 2a1 1 0 001.42 0l4-4a1 1 0 00-1.42-1.42z" clip-rule="evenodd" />
</svg>
</span>
</div>
<!-- Horizontal Checkbox with Label and No Icon -->
<div class="checkbox-container">
<input type="checkbox" id="checkbox2" class="checkbox checkbox-primary">
<label for="checkbox2" class="checkbox-label">Label without Icon</label>
</div>
<!-- Horizontal Checkbox with No Label and Icon -->
<div class="checkbox-container">
<input type="checkbox" id="checkbox3" class="checkbox checkbox-primary">
<span class="checkbox-icon">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11.41l-3.3 3.29-1.29-1.29a1 1 0 10-1.42 1.42l2 2a1 1 0 001.42 0l4-4a1 1 0 00-1.42-1.42z" clip-rule="evenodd" />
</svg>
</span>
</div>
<!-- Vertical Checkbox with Label and Icon -->
<div class="checkbox-container flex-col">
<input type="checkbox" id="checkbox4" class="checkbox checkbox-primary">
<label for="checkbox4" class="checkbox-label">Vertical Label with Icon</label>
<span class="checkbox-icon">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-11.41l-3.3 3.29-1.29-1.29a1 1 0 10-1.42 1.42l2 2a1 1 0 001.42 0l4-4a1 1 0 00-1.42-1.42z" clip-rule="evenodd" />
</svg>
</span>
</div>
</div>

View File

@@ -0,0 +1,51 @@
const checkboxData = [
{ label: 'Option 1', position: 'right' },
{ label: 'Option 2', icon: '📞', position: 'right' },
{ label: 'Option 3', icon: '📞', position: 'left' },
{ label: 'Option 4', icon: '📞', position: 'left' },
];
function createCheckboxComponent({ label, icon, position, orientation }) {
const checkboxContainer = document.createElement('div');
checkboxContainer.className = `checkbox-container ${orientation === 'vertical' ? 'flex-col' : ''}`;
const checkboxInput = document.createElement('input');
checkboxInput.type = 'checkbox';
checkboxInput.className = 'checkbox checkbox-primary';
checkboxInput.id = label;
const checkboxLabel = document.createElement('label');
checkboxLabel.className = `checkbox-label checkbox-label-${position}`;
checkboxLabel.htmlFor = label;
if (icon) {
const iconElement = document.createElement('span');
iconElement.className = 'icon';
iconElement.innerText = icon;
checkboxLabel.appendChild(iconElement);
}
if (label) {
const labelText = document.createElement('span');
labelText.innerText = label;
checkboxLabel.appendChild(labelText);
}
if (position === 'left' || orientation === 'vertical') {
checkboxContainer.appendChild(checkboxLabel);
checkboxContainer.appendChild(checkboxInput);
} else {
checkboxContainer.appendChild(checkboxInput);
checkboxContainer.appendChild(checkboxLabel);
}
return checkboxContainer;
}
document.addEventListener('DOMContentLoaded', () => {
const checkboxContainer = document.getElementById('checkbox-container');
checkboxData.forEach(checkboxConfig => {
const checkboxComponent = createCheckboxComponent(checkboxConfig);
checkboxContainer.appendChild(checkboxComponent);
});
});

View File

@@ -0,0 +1,41 @@
body {
font-family: 'Inter', sans-serif;
background-color: var(--_app-global-grayscale-100, #F2F4F7);
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
min-height: 100vh;
}
.content-container {
flex: 1;
padding-bottom: 4rem;
background-color: var(--_app-global-grayscale-100, #F2F4F7);
}
.sticky-footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
padding: 1rem;
background-color: #fff;
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
}
.header-container {
width: 100%;
background-color: var(--_app-global-grayscale-100, #F2F4F7);
padding: 1rem;
box-shadow: none;
}
#plan-header {
font-size: 18px;
font-weight: 600;
margin-bottom: 16px;
color: #18191E;
}

View File

@@ -0,0 +1,114 @@
.dropdown-container {
width: var(--Chart-Module-Width, 325px);
margin-bottom: 1rem;
position: relative;
}
.dropdown-label {
display: flex;
height: var(--Icon-Sizes-Input, 20px);
flex-direction: column;
justify-content: flex-end;
flex: 1 0 0;
color: var(--app-input-text-label-day, #1E2024);
font-family: Inter, sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 700;
line-height: 20px;
margin-bottom: 0.5rem;
}
.dropdown-description {
align-self: stretch;
color: var(--app-input-text-label-light-day, #344054);
font-family: Inter, sans-serif;
font-size: 13px;
font-style: normal;
font-weight: 500;
line-height: 16px;
margin-top: 0.5rem;
}
.dropdown-placeholder {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
flex: 1 0 0;
overflow: hidden;
color: var(--app-input-text-placeholder-text-day, #7D8188);
text-overflow: ellipsis;
font-family: Inter, sans-serif;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
}
.dropdown-button {
width: var(--Chart-Module-Width, 325px);
height: 48px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.5rem;
border: 1px solid var(--app-input-element-stroke-day, #98A2B3);
border-radius: 4px;
background: var(--app-input-element-background-day, #F9FAFB);
cursor: pointer;
}
.dropdown-list {
display: none;
flex-direction: column;
align-items: flex-start;
width: var(--Chart-Module-Width, 325px);
max-height: 200px;
overflow-y: auto;
padding: var(--Input-Element-Radius-CTA-S, 6px) 2px var(--Spacing-Keywords, 0px) 2px;
border: 1px solid var(--app-input-element-stroke-day, #98A2B3);
border-radius: 0 0 4px 4px;
background: var(--app-input-element-background-day, #F9FAFB);
position: absolute;
left: 0;
z-index: 10;
}
.dropdown-list-with-description {
top: 75%;
}
.dropdown-list-no-description {
top: 100%;
}
.dropdown-item {
display: flex;
height: 40px;
padding: 8px var(--Icon-Sizes-Input, 20px) 8px 8px;
justify-content: space-between;
align-items: flex-start;
align-self: stretch;
cursor: pointer;
transition: background-color 0.3s, color 0.3s;
}
.dropdown-item:hover {
background-color: #0DC3FF;
}
.dropdown-item-text {
flex: 1 0 0;
color: var(--app-input-text-user-input-day, #1E2024);
font-family: Inter, sans-serif;
font-size: 16px;
font-style: normal;
font-weight: 400;
line-height: 24px;
transition: color 0.3s;
}
.dropdown-item:hover .dropdown-item-text {
color: var(--app-input-text-user-input-day, #1E2024);
font-weight: 600;
}

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dropdown Component Example</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/daisyui@1.15.0/dist/full.css" rel="stylesheet">
<link rel="stylesheet" href="dropdown.css">
</head>
<body class="bg-gray-100 p-10">
<h1 class="text-2xl font-bold mb-4">Dropdown Component Example</h1>
<div id="dropdown-container"></div>
<script>
console.log("Loading dropdown.js...");
</script>
<script src="dropdown.js"></script>
</body>
</html>

View File

@@ -0,0 +1,87 @@
const dropdownData = [
{ label: 'Options', placeholder: 'Select an option', description: 'Choose one of the following items', items: ['Item 1', 'Item 2', 'Item 3'] },
{ placeholder: 'Select without label', items: ['Item A', 'Item B', 'Item C', 'Item D', 'Item E', 'Item F', 'Item G', 'Item H', 'Item I', 'Item J', 'Item K'] },
{ label: 'Options 2', placeholder: 'Choose an item', description: 'Additional description lorem ipsum', items: ['Option 1', 'Option 2', 'Option 3'] },
];
function createDropdownComponent({ label, placeholder, description, items }) {
const dropdownContainer = document.createElement('div');
dropdownContainer.className = 'dropdown-container mb-6';
if (label) {
const labelElement = document.createElement('label');
labelElement.className = 'dropdown-label block text-gray-700 text-sm font-bold mb-2';
labelElement.innerText = label;
dropdownContainer.appendChild(labelElement);
}
const buttonElement = document.createElement('div');
buttonElement.className = 'dropdown-button';
buttonElement.innerText = placeholder || 'Select an option';
dropdownContainer.appendChild(buttonElement);
const dropdownList = document.createElement('div');
dropdownList.className = 'dropdown-list';
dropdownList.style.display = 'none';
if (description) {
dropdownList.classList.add('dropdown-list-with-description');
} else {
dropdownList.classList.add('dropdown-list-no-description');
}
items.forEach(item => {
const itemElement = document.createElement('div');
itemElement.className = 'dropdown-item';
const itemText = document.createElement('span');
itemText.className = 'dropdown-item-text';
itemText.innerText = item;
itemElement.appendChild(itemText);
itemElement.addEventListener('click', () => {
buttonElement.innerHTML = '';
buttonElement.className = 'dropdown-button selected-dropdown-item';
const selectedItemText = document.createElement('span');
selectedItemText.className = 'selected-dropdown-item-text';
selectedItemText.innerText = item;
buttonElement.appendChild(selectedItemText);
dropdownList.style.display = 'none';
});
dropdownList.appendChild(itemElement);
});
buttonElement.addEventListener('click', (event) => {
event.stopPropagation();
dropdownList.style.display = dropdownList.style.display === 'none' ? 'flex' : 'none';
});
document.addEventListener('click', (event) => {
if (!dropdownContainer.contains(event.target)) {
dropdownList.style.display = 'none';
}
});
dropdownContainer.appendChild(dropdownList);
if (description) {
const descriptionElement = document.createElement('p');
descriptionElement.className = 'dropdown-description text-gray-600 text-xs italic mt-2';
descriptionElement.innerText = description;
dropdownContainer.appendChild(descriptionElement);
}
return dropdownContainer;
}
document.addEventListener('DOMContentLoaded', () => {
console.log("Document loaded, rendering dropdowns...");
const dropdownContainer = document.getElementById('dropdown-container');
dropdownData.forEach(dropdownConfig => {
const dropdownComponent = createDropdownComponent(dropdownConfig);
dropdownContainer.appendChild(dropdownComponent);
});
});

View File

@@ -0,0 +1,43 @@
.duo-layout {
display: flex;
flex-direction: row;
gap: 16px;
justify-content: center;
padding: 0 16px;
}
.duo-layout .media-item {
width: 500px;
height: 720px;
flex-shrink: 0;
overflow: hidden;
}
.duo-layout .media-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
@media (max-width: 640px) {
.duo-layout {
justify-content: space-between;
gap: 8px;
padding: 0 16px;
max-width: 100%;
}
.duo-layout .media-item {
width: calc(50% - 5px);
max-width: 200px;
height: 45vh;
margin: 0;
}
.duo-layout .media-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
}

View File

@@ -0,0 +1,10 @@
.sticky-footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
padding: 1rem;
background-color: #fff;
box-shadow: 0 -2px 5px rgba(0, 0, 0, 0.1);
}

View File

@@ -0,0 +1,285 @@
body {
margin: 0;
font-family: 'Montserrat', sans-serif;
position: relative;
}
.header-background {
height: 80vh;
background-size: cover;
background-position: center;
position: relative;
z-index: 1;
}
.remaining-background {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 20vh;
background-color: black;
z-index: 1;
}
.container {
width: 78%;
margin: 0 auto;
display: flex;
justify-content: space-between;
align-items: center;
z-index: 3;
}
.logo {
width: 160px;
height: auto;
flex-shrink: 0;
margin-left: 0;
}
.nav-link {
color: #f6f6f6;
font-family: 'Montserrat', sans-serif;
font-size: 16px;
font-style: normal;
font-weight: 800;
line-height: normal;
letter-spacing: -0.32px;
margin-right: 1.5vw;
}
.menu-button {
display: none;
background: none;
border: none;
cursor: pointer;
}
.menu-icon {
width: 30px;
height: auto;
}
.text-box {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 0.5vh;
width: 30vw;
height: 35vh;
padding: 3vh 3.5vw;
border-radius: 0.5vh;
background-color: #161616;
color: #f6f6f6;
margin-bottom: 1vh;
transform: translateY(-5vh);
}
.headline1 {
color: #f6f6f6;
font-family: 'Montserrat', sans-serif;
font-size: 36px;
font-style: normal;
font-weight: 800;
line-height: 44px;
letter-spacing: -0.72px;
margin: 0;
}
.headline2 {
font-family: 'Montserrat', sans-serif;
font-size: 36px;
font-style: normal;
font-weight: 800;
line-height: 44px;
letter-spacing: -0.72px;
background: linear-gradient(104deg, #00FFC2 0%, #00C0FF 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent;
margin: 0;
}
.description-text {
font-family: 'Montserrat', sans-serif;
font-size: 22px;
font-style: normal;
font-weight: 600;
line-height: 32px;
color: #f6f6f6;
margin-top: 2vh;
max-width: 100%;
}
.text-highlight {
background: linear-gradient(103deg, #00FFC2 15.48%, #00C0FF 39.9%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-family: 'Montserrat', sans-serif;
font-size: 22px;
font-style: normal;
font-weight: 700;
line-height: 25px;
letter-spacing: -0.44px;
}
.email-signup-box {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 1vh;
width: 30vw;
padding: 2vh 3.5vw;
border-radius: 0.5vh;
background-color: #292F38;
color: #f6f6f6;
box-shadow: 0px 0.5vh 1.5vh rgba(0, 0, 0, 0.25);
transform: translateY(-7vh);
}
.email-input {
width: 284px;
height: 48px;
border-radius: 4px;
border: 1px solid #667085;
background-color: #161616;
color: #ffffff;
padding: 0.5vh 1vw;
}
.gradient-button {
background: linear-gradient(90deg, #00ffc2 0%, #00c0ff 100%);
color: white;
padding: 1vh 2vw;
border-radius: 0.4vh;
border: none;
cursor: pointer;
transition: background 0.3s ease;
}
.header-gradient {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 200vh;
background: linear-gradient(to bottom, rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0) 80%);
z-index: 2;
pointer-events: none;
}
@media only screen and (max-width: 768px) {
.header-container {
background-size: 250%;
background-position: center top;
flex-direction: column;
padding: 2vh 5vw;
}
.header-background {
background-size: cover;
background-position: center;
height: 80vh;
background-color: black;
}
.container {
width: auto;
margin: 0;
padding: 0;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.logo {
width: 180px;
height: auto;
margin-top: 40px;
margin-left: 45px;
}
.nav-link {
display: none;
}
.menu-button {
display: flex;
align-items: center;
margin-right: 40px;
margin-top: 45px;
}
.menu-icon {
display: block;
width: 33px;
height: auto;
}
.text-box, .email-signup-box {
width: 80vw;
margin-left: -7vw;
margin-right: 0;
text-align: left;
transform: translateY(3vh);
}
.text-box {
padding: 3vh 4vw;
height: auto;
}
.email-signup-box {
display: flex;
flex-direction: column;
align-items: stretch;
padding: 20px;
background-color: #292F38;
color: #f6f6f6;
box-sizing: border-box;
border-radius: 8px;
height: auto;
min-height: 210px;
transform: translateY(1vh);
}
.email-input {
width: 87.5%;
height: 48px;
padding: 12px;
border-radius: 4px;
border: 1px solid #667084;
background-color: #161616;
color: #f6f6f6;
margin: 0;
margin-bottom: 10px;
box-sizing: border-box;
position: absolute;
top: 76px;
left: 20px;
}
.gradient-button {
width: 87.5%;
height: 48px;
padding: 12px;
background: linear-gradient(90deg, #00ffc2 0%, #00c0ff 100%);
color: #ffffff;
text-align: center;
cursor: pointer;
border: none;
border-radius: 16px;
box-sizing: border-box;
position: absolute;
top: 140px;
left: 13px;
}
.gradient-button:hover {
background: linear-gradient(90deg, #00c0ff 0%, #00ffc2 100%);
}
}

View File

@@ -0,0 +1,66 @@
<!-- components/header.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Tailwind CSS CDN -->
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
<!-- DaisyUI CDN -->
<link href="https://cdn.jsdelivr.net/npm/daisyui@2.15.3/dist/full.css" rel="stylesheet">
<!-- Link to the CSS file -->
<link rel="stylesheet" href="components/header.css">
<title>Header Component</title>
</head>
<body>
<header class="relative w-full bg-cover bg-center header-background" style="height: 100vh; background-image: url('https://s3-alpha-sig.figma.com/img/193d/32f1/73586125aba9fb9700efa4c194bb4fd2?Expires=1725840000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=XPsu3f44VaAU9oU0vw4rWpKWYIEyYYXX3IKJLZGipBD0FqufIBt6fB5Ng3kuY~hx~TWh5iNa4vggL5IwCXf6rLyyZWLv6dydPIdGKzM3dSiVnVwQA5xwtJ5rXvxUMBbI9kXJRxq96~byLWCPjOPNWtbibTG7ptbcs98bkBFF8TBSPskgvx~XNorIq1Q2P2uaxMe25m7LQ89wFXsVSbWDn75j7Gkvyutu2vAiz2E9bxG7~o3naMwz1fpec8tSkgN9XGqnXKruYYyzJ2pDc4tz3PC80vVncK1-Oh-MPXVdlLQPQjd8wM1CmNWGuz2FN7Q7KCF-bXeRl8eq-jXoeNjRmw__');">
<!-- Gradient overlay -->
<div class="header-gradient"></div>
<div class="absolute inset-0 bg-black opacity-20"></div>
<!-- Black background for the remaining 20% -->
<div class="remaining-background"></div>
<div class="relative z-10 flex items-center justify-between p-4 container">
<!-- Logo -->
<div class="flex items-center">
<img src='./static/img/icons/Smatchit_Logo.png' class="logo" alt="Logo">
</div>
<!-- Navigation Links (Visible in Desktop Mode) -->
<nav class="space-x-8 text-white nav-links">
<a href="#" class="nav-link">Pour les entreprises</a>
<a href="#" class="nav-link">Contact</a>
</nav>
<!-- Menu Button (Visible in Mobile Mode) -->
<button class="menu-button">
<img src='./static/img/icons/menu.png' class="menu-icon" alt="Menu">
</button>
</div>
<!-- Main Content -->
<div class="relative z-20 flex flex-col items-start justify-center h-full text-left text-white px-8" style="padding-top: 4vh; margin-left: 10vw;">
<!-- Text Box -->
<div class="text-box">
<p class="headline1">Votre</p>
<p class="headline2">agent de recrutement</p>
<p class="headline1">personnel 24/7.</p>
<p class="description-text">
Laissez <span class="text-highlight">smatchit</span> faire pour trouver votre job, détendez-vous et soyez à lheure à vos futurs entretiens 😊
</p>
</div>
<!-- Email Signup Box -->
<div class="email-signup-box mt-4">
<p class="mb-2">Soyez alerté du lancement de <span class="text-highlight">smatchit</span> :</p>
<div class="flex items-center w-full space-x-2">
<input type="email" placeholder="Enter your e-mail" class="email-input" />
<button type="submit" class="gradient-button">SEND</button>
</div>
</div>
</div>
</header>
</body>
</html>

View File

@@ -0,0 +1,13 @@
// components/header/header.js
document.addEventListener('DOMContentLoaded', () => {
const button = document.querySelector('.btn-primary');
button.addEventListener('click', () => {
const emailInput = document.querySelector('.input[type="email"]').value;
if (emailInput) {
alert(`Email ${emailInput} submitted successfully!`);
} else {
alert('Please enter a valid email.');
}
});
});

View File

@@ -0,0 +1,8 @@
.inset-wrapper {
max-width: 1024px;
margin: 0 auto;
box-shadow: none;
border-radius: 0;
padding: 0;
background-color: transparent;
}

View File

@@ -0,0 +1,4 @@
<!-- media-item.html -->
<div class="media-item">
<img src="{{src}}" alt="{{alt}}" class="w-full h-auto object-cover">
</div>

View File

@@ -0,0 +1,72 @@
// layout-manager.js
document.addEventListener("DOMContentLoaded", function () {
const mediaContainer = document.getElementById('media-container');
// Media items with the specified image URL repeated
const mediaItems = [
{ type: 'image', src: 'https://s3-alpha-sig.figma.com/img/37a7/42fb/1daabd5424c6093ca79a6d502b3b84ef?Expires=1724630400&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=FgQK8BhmZm52syueYHL8d33N9v48-lePOhb~KQgE528f-GZn8a8HXap5OvWlCdKaf2nZLlFvmgWgpnuz7iekJqEAS95CknKbniYODvBDOGMVIcHrU7YthPZ~YqZSE7pEANVBVEwkB9-1zJ77gT9uEMryjd-xb44NjnBhfLPkP4B9qlqkbuehRRhLGPBnYA9q3PHpf5ocx7j0~xAbomT~EFX2bzwBu70gKN0qTFVRy8uNu8USYah2YotQH58ChxcEPokhPxENAdNCWeDodsWVFrldbeU0CgVzCrn3MLYu9Ep96r7tjAvKfgQQqC6eORHyM-citVFu1DlJx8-CUN26RQ__', alt: 'Image 1' },
{ type: 'image', src: 'https://s3-alpha-sig.figma.com/img/37a7/42fb/1daabd5424c6093ca79a6d502b3b84ef?Expires=1724630400&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=FgQK8BhmZm52syueYHL8d33N9v48-lePOhb~KQgE528f-GZn8a8HXap5OvWlCdKaf2nZLlFvmgWgpnuz7iekJqEAS95CknKbniYODvBDOGMVIcHrU7YthPZ~YqZSE7pEANVBVEwkB9-1zJ77gT9uEMryjd-xb44NjnBhfLPkP4B9qlqkbuehRRhLGPBnYA9q3PHpf5ocx7j0~xAbomT~EFX2bzwBu70gKN0qTFVRy8uNu8USYah2YotQH58ChxcEPokhPxENAdNCWeDodsWVFrldbeU0CgVzCrn3MLYu9Ep96r7tjAvKfgQQqC6eORHyM-citVFu1DlJx8-CUN26RQ__', alt: 'Image 2' },
// { type: 'image', src: 'https://s3-alpha-sig.figma.com/img/37a7/42fb/1daabd5424c6093ca79a6d502b3b84ef?Expires=1724630400&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=FgQK8BhmZm52syueYHL8d33N9v48-lePOhb~KQgE528f-GZn8a8HXap5OvWlCdKaf2nZLlFvmgWgpnuz7iekJqEAS95CknKbniYODvBDOGMVIcHrU7YthPZ~YqZSE7pEANVBVEwkB9-1zJ77gT9uEMryjd-xb44NjnBhfLPkP4B9qlqkbuehRRhLGPBnYA9q3PHpf5ocx7j0~xAbomT~EFX2bzwBu70gKN0qTFVRy8uNu8USYah2YotQH58ChxcEPokhPxENAdNCWeDodsWVFrldbeU0CgVzCrn3MLYu9Ep96r7tjAvKfgQQqC6eORHyM-citVFu1DlJx8-CUN26RQ__', alt: 'Image 3' },
{ type: 'image', src: 'https://s3-alpha-sig.figma.com/img/37a7/42fb/1daabd5424c6093ca79a6d502b3b84ef?Expires=1724630400&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=FgQK8BhmZm52syueYHL8d33N9v48-lePOhb~KQgE528f-GZn8a8HXap5OvWlCdKaf2nZLlFvmgWgpnuz7iekJqEAS95CknKbniYODvBDOGMVIcHrU7YthPZ~YqZSE7pEANVBVEwkB9-1zJ77gT9uEMryjd-xb44NjnBhfLPkP4B9qlqkbuehRRhLGPBnYA9q3PHpf5ocx7j0~xAbomT~EFX2bzwBu70gKN0qTFVRy8uNu8USYah2YotQH58ChxcEPokhPxENAdNCWeDodsWVFrldbeU0CgVzCrn3MLYu9Ep96r7tjAvKfgQQqC6eORHyM-citVFu1DlJx8-CUN26RQ__', alt: 'Image 4' },
];
const useQuatreA = false; // Set this to true for Quatre A, false for Quatre B
// Apply the appropriate layout based on the number of media items
const applyLayout = () => {
mediaContainer.innerHTML = ''; // Clear existing content
const itemCount = mediaItems.length;
if (itemCount === 1) {
// Single Image Layout
mediaContainer.className = 'single-layout';
mediaContainer.innerHTML += `<div class="media-item">${renderMedia(mediaItems[0])}</div>`;
} else if (itemCount === 2) {
// Duo Layout
mediaContainer.className = 'duo-layout';
mediaItems.forEach(item => {
mediaContainer.innerHTML += `<div class="media-item">${renderMedia(item)}</div>`;
});
} else if (itemCount === 3) {
// Trio Layout
mediaContainer.className = 'trio-layout';
mediaContainer.innerHTML += `<div class="left-column media-item">${renderMedia(mediaItems[0])}</div>`;
mediaContainer.innerHTML += `
<div class="right-column">
<div class="media-item">${renderMedia(mediaItems[1])}</div>
<div class="media-item">${renderMedia(mediaItems[2])}</div>
</div>`;
return;
} else if (itemCount >= 4) {
if (useQuatreA) {
// Quatre A Layout
mediaContainer.className = 'grid grid-cols-2 gap-4';
mediaItems.forEach(item => {
mediaContainer.innerHTML += `<div class="media-item">${renderMedia(item)}</div>`;
});
} else {
// Quatre B Layout
mediaContainer.className = 'quatre-b-layout';
mediaContainer.innerHTML += `<div class="top-image">${renderMedia(mediaItems[0])}</div>`;
mediaContainer.innerHTML += `<div class="bottom-row">`;
for (let i = 1; i < Math.min(5, itemCount); i++) {
mediaContainer.innerHTML += `<div class="media-item">${renderMedia(mediaItems[i])}</div>`;
}
mediaContainer.innerHTML += `</div>`;
}
}
};
// Function to render media based on its type
const renderMedia = (item) => {
if (item.type === 'image') {
return `<img src="${item.src}" alt="${item.alt}">`; /* Ensure images fill their containers */
} else if (item.type === 'video') {
return `<video src="${item.src}" controls class="w-full h-auto"></video>`;
}
return '';
};
// Apply the layout
applyLayout();
});

View File

@@ -0,0 +1,21 @@
document.addEventListener("DOMContentLoaded", function() {
const mediaType = 'image';
const hasPlayButton = true;
const image = document.getElementById('media-image');
const video = document.getElementById('media-video');
const playButton = document.getElementById('play-button');
const caption = document.getElementById('caption');
if (mediaType === 'image') {
image.classList.remove('hidden');
} else if (mediaType === 'video') {
video.classList.remove('hidden');
}
if (hasPlayButton && mediaType === 'video') {
playButton.classList.remove('hidden');
}
});

View File

@@ -0,0 +1,72 @@
.quatre-b-layout {
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
.quatre-b-layout .top-image {
display: flex;
width: 100%;
height: 440px;
flex-direction: column;
align-items: flex-start;
gap: 16px;
flex-shrink: 0;
grid-column: 1 / span 3;
}
.quatre-b-layout .top-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.quatre-b-layout .bottom-row {
display: contents;
}
.quatre-b-layout .media-item {
overflow: hidden;
grid-column: span 1;
width: 100%;
}
.quatre-b-layout .media-item img {
width: 100%;
height: auto;
object-fit: contain;
}
@media (max-width: 768px) {
.quatre-b-layout {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto 1fr;
gap: 10px;
}
.quatre-b-layout .top-image {
width: 100%;
height: auto;
grid-column: 1 / span 3;
}
.quatre-b-layout .bottom-row {
display: contents;
}
.quatre-b-layout .media-item {
width: 100%;
height: auto;
grid-column: span 1;
}
.quatre-b-layout .media-item img {
width: 100%;
height: auto;
object-fit: cover;
}
}

View File

@@ -0,0 +1,67 @@
.radio-container {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
width: 130px;
}
.radio-input {
appearance: none;
border: 2px solid #98A2B3;
border-radius: 50%;
width: var(--Chart-Column-Margin, 24px);
height: var(--Chart-Column-Margin, 24px);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
flex-shrink: 0;
position: relative;
}
.radio-input:checked {
border-color: #0DC3FF;
background-color: #0DC3FF;
}
.radio-input:checked::before {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 10px;
height: 10px;
background-color: white;
border-radius: 50%;
}
.radio-label {
display: flex;
align-items: center;
color: var(--app-input-text-label-day, #1E2024);
font-family: Inter, sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 20px;
}
.icon {
margin-right: 0.5rem;
}
.radio-label-left {
justify-content: flex-end;
margin-left: 10px;
order: 2;
flex-grow: 1;
}
.radio-label-right {
justify-content: flex-start;
margin-right: 10px;
order: 1;
flex-grow: 1;
}

View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Reusable Components</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="dropdown-container"></div>
<div id="radiobutton-container"></div>
<script src="radiobutton.js"></script>
</body>
</html>

View File

@@ -0,0 +1,58 @@
const radiobuttonData = [
{ label: 'Option 1', position: 'right' },
{ label: 'Option 2', icon: '📞', position: 'right' },
{ label: 'Option 3', icon: '📞', position: 'left' },
{ label: 'Option 4', icon: '📞', position: 'left' },
];
function createRadiobuttonComponent({ label, icon, position }) {
const radioContainer = document.createElement('div');
radioContainer.className = 'radio-container';
const radioInput = document.createElement('input');
radioInput.type = 'radio';
radioInput.className = 'radio-input';
radioInput.name = 'radio';
radioInput.id = label;
const radioLabel = document.createElement('label');
radioLabel.className = `radio-label`;
radioLabel.htmlFor = label;
if (position === 'left') {
radioContainer.appendChild(radioInput);
}
if (icon) {
const iconElement = document.createElement('span');
iconElement.className = 'icon';
iconElement.innerText = icon;
radioLabel.appendChild(iconElement);
}
if (label) {
const labelText = document.createElement('span');
labelText.innerText = label;
radioLabel.appendChild(labelText);
}
if (position === 'right') {
radioContainer.appendChild(radioInput);
}
if (position === 'left') {
radioContainer.appendChild(radioLabel);
} else {
radioContainer.insertBefore(radioLabel, radioInput);
}
return radioContainer;
}
document.addEventListener('DOMContentLoaded', () => {
const radiobuttonContainer = document.getElementById('radiobutton-container');
radiobuttonData.forEach(radiobuttonConfig => {
const radiobuttonComponent = createRadiobuttonComponent(radiobuttonConfig);
radiobuttonContainer.appendChild(radiobuttonComponent);
});
});

View File

@@ -0,0 +1,9 @@
<!-- single-column.html -->
<div class="single-column">
<div class="optional-header">
<h3>Headline 3 optional</h3>
<h4>Headline 4 optional</h4>
</div>
<p>Water polo has been part of the Summer Olympics program since the second games, in 1900...</p>
</div>

View File

@@ -0,0 +1,39 @@
.custom-tabs {
background-color: #f1f1f1;
padding: 0.5rem;
border-radius: 50px;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.custom-tab {
padding: 0.5rem 1.5rem;
cursor: pointer;
transition: background-color 0.3s, color 0.3s;
font-size: 15px;
font-weight: 600;
color: #6b7280;
background-color: #e5e7eb;
margin-left: -5px;
border-radius: 50px;
z-index: 1;
}
.custom-tab:first-child {
margin-left: 0;
}
.custom-tab-active {
background-color: #000;
color: #fff;
font-weight: 700;
z-index: 2;
}
.custom-tab-inactive {
color: #9CA3AF;
font-weight: 500;
z-index: 1;
}

View File

@@ -0,0 +1,4 @@
function setLayout(layoutClass) {
const container = document.getElementById('text-layout-container');
container.className = `content-container ${layoutClass}`;
}

View File

@@ -0,0 +1,132 @@
.text-media-1-wrapper {
max-width: 1608px;
margin: 0 auto;
padding: 0 16px;
background-color: white;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
border-radius: 8px;
}
.text-media-1 {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0;
flex-direction: row;
}
.text-media-1.reverse {
flex-direction: row-reverse;
}
.text-media-1 .text-section,
.text-media-1 .media-section {
width: 50%;
}
.text-media-1 .text-section {
padding-right: 16px;
display: flex;
flex-direction: column;
justify-content: flex-start;
margin-top: 0;
padding: var(--text-padding-vertical-desktop, 8px) 0;
align-items: flex-start;
align-self: stretch;
}
.text-media-1 .media-section {
padding-left: 0;
padding-right: 0;
margin-top: 16px;
}
.text-media-1 .text-section h3 {
color: var(--app-text-stroke-text-stroke-day, #18191E);
font-family: Montserrat;
font-size: 32px;
font-style: normal;
font-weight: 700;
line-height: 40px;
letter-spacing: -0.64px;
margin-bottom: 0.2rem;
margin-top: 0;
text-align: left;
}
.text-media-1 .text-section h4 {
color: var(--app-text-stroke-text-stroke-day, #18191E);
font-family: Montserrat;
font-size: 28px;
font-style: normal;
font-weight: 600;
line-height: 40px;
letter-spacing: -0.56px;
margin-bottom: 1rem;
margin-top: 0;
text-align: left;
}
.text-media-1 .text-section p {
color: var(--app-text-stroke-text-stroke-day, #18191E);
font-family: Inter;
font-size: 18px;
font-style: normal;
font-weight: 500;
line-height: 28px;
margin-top: 0;
margin-bottom: 0;
width: 100%;
text-align: left;
max-width: 100%;
}
.text-media-1 .media-section img {
width: 100%;
height: auto;
flex-shrink: 0;
object-fit: cover;
border-radius: 8px;
max-width: 100%;
}
@media (max-width: 640px) {
.text-media-1,
.text-media-1.reverse {
flex-direction: column;
align-items: flex-start;
padding: 0 16px;
}
.text-media-1 .text-section,
.text-media-1 .media-section,
.text-media-1.reverse .text-section,
.text-media-1.reverse .media-section {
width: 100%;
max-width: 100%;
}
.text-media-1 .media-section img,
.text-media-1.reverse .media-section img {
margin-bottom: 20px;
}
.text-media-1 .text-section h3,
.text-media-1 .text-section h4,
.text-media-1.reverse .text-section h3,
.text-media-1.reverse .text-section h4 {
text-align: left;
margin-bottom: 8px;
}
.text-media-1 .text-section p,
.text-media-1.reverse .text-section p {
text-align: left;
margin-bottom: 20px;
}
.text-media-1-wrapper {
padding-left: 0;
padding-right: 0;
}
}

View File

@@ -0,0 +1,13 @@
<!-- text-media-1.html -->
<div class="text-media-1-wrapper">
<div class="text-media-1">
<div class="text-section">
<h3></h3> <!-- Headline 3 -->
<h4></h4> <!-- Headline 4 -->
<p></p> <!-- Body Text -->
</div>
<div class="media-section">
<img src="" alt="Description of image">
</div>
</div>
</div>

View File

@@ -0,0 +1,31 @@
document.addEventListener("DOMContentLoaded", function() {
const config = {
order: 'media-text', // or 'media-text'
h3: 'Your Headline 3 Text',
h4: 'Your Headline 4 Text',
bodyText: 'Body Text Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.sdsdsd',
imageUrl: 'https://s3-alpha-sig.figma.com/img/37a7/42fb/1daabd5424c6093ca79a6d502b3b84ef?Expires=1725235200&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=aiQBLdi9Fj2GEiVQIUFmOcfAnAh4W79hJej42foev128u4u2p5AEfKLOse~ksw7eOT3QvQsqtKNsbcwcaBzwUljFVc-SaQkeY7bfgDXwCQ~aMOysamP-HbYx3D0cIIZQwJorkddZS9smInFTzHObShtlwVU05hN~yPBGVk0AaDRZ2oICAtH1aJF~GMQshvpElVpUQRGvpY5~WZOAI9f3ESrfij~zw9WwKVSlK0TrJiNzKhVW14eff4Y8KCkoWA9KUINS8BOiXu5COH~MDo4MXveP805~bRjAoji4G4DKwmUNvdGWJGRYRwoIzJ9kMIWQVhuvWi8Yk4naDkLDCXYtDQ__'
};
fetch('components/text-media-1.html')
.then(response => response.text())
.then(data => {
document.getElementById('text-media-1-container').innerHTML = data;
const wrapper = document.querySelector('.text-media-1');
const h3 = document.querySelector('.text-section h3');
const h4 = document.querySelector('.text-section h4');
const p = document.querySelector('.text-section p');
const img = document.querySelector('.media-section img');
h3.textContent = config.h3;
h4.textContent = config.h4;
p.textContent = config.bodyText;
img.src = config.imageUrl;
if (config.order === 'media-text') {
wrapper.classList.add('reverse');
}
})
.catch(error => console.error('Error loading text-media-1 component:', error));
});

View File

@@ -0,0 +1,109 @@
.text-media-2-wrapper {
max-width: 1608px;
margin: 0 auto;
padding-left: 360px;
padding-right: 292px;
background-color: white;
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
border-radius: 8px;
}
.text-media-2 {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0;
flex-direction: row;
}
.text-media-2.reverse {
flex-direction: row-reverse;
}
.text-media-2 .text-section,
.text-media-2 .media-section {
width: 50%;
}
.text-media-2 .text-section {
padding-right: 20px;
display: flex;
flex-direction: column;
justify-content: flex-start;
margin-top: 0;
padding: var(--text-padding-vertical-desktop, 8px) var(--text-padding-horizontal-desktop, 16px) var(--text-padding-vertical-desktop, 8px) var(--Spacing-Keywords, 0px);
align-items: flex-start;
align-self: stretch;
}
.text-media-2 .media-section {
padding-left: 0;
padding-right: 0;
}
.text-media-2 .text-section h3 {
color: var(--app-text-stroke-text-stroke-day, #18191E);
font-family: Montserrat;
font-size: 44px;
font-style: normal;
font-weight: 700;
line-height: 56px;
letter-spacing: -0.88px;
margin-bottom: 1rem;
margin-top: 0;
}
.text-media-2 .media-section img {
width: 100%;
height: auto;
object-fit: cover;
border-radius: 8px;
margin-bottom: 8px;
max-width: 100%;
}
.text-media-2 .media-section .image-caption {
font-family: Inter;
font-size: 14px;
color: #555;
margin-top: 0;
margin-bottom: 0;
text-align: center;
}
@media (max-width: 640px) {
.text-media-2 {
flex-direction: column;
align-items: flex-start;
padding: 0 12px;
}
.text-media-2.reverse {
flex-direction: column;
}
.text-media-2 .text-section,
.text-media-2 .media-section {
width: 100%;
max-width: 95%;
}
.text-media-2 .media-section img {
margin-bottom: 20px;
}
.text-media-2 .text-section h3 {
text-align: left;
margin-bottom: 8px;
}
.text-media-2 .media-section .image-caption {
text-align: left;
}
.text-media-2-wrapper {
padding-left: 0;
padding-right: 0;
max-width: 100%;
}
}

View File

@@ -0,0 +1,12 @@
<!-- text-media-2.html -->
<div class="text-media-2-wrapper">
<div class="text-media-2">
<div class="media-section">
<img src="" alt="Description of image">
<p class="image-caption"></p> <!-- Optional image caption -->
</div>
<div class="text-section">
<h3></h3> <!-- Main Text -->
</div>
</div>
</div>

View File

@@ -0,0 +1,42 @@
document.addEventListener("DOMContentLoaded", function() {
const config = {
order: 'text-media', // or 'media-text'
mainText: 'Headline Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.',
imageUrl: 'https://s3-alpha-sig.figma.com/img/37a7/42fb/1daabd5424c6093ca79a6d502b3b84ef?Expires=1724630400&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=FgQK8BhmZm52syueYHL8d33N9v48-lePOhb~KQgE528f-GZn8a8HXap5OvWlCdKaf2nZLlFvmgWgpnuz7iekJqEAS95CknKbniYODvBDOGMVIcHrU7YthPZ~YqZSE7pEANVBVEwkB9-1zJ77gT9uEMryjd-xb44NjnBhfLPkP4B9qlqkbuehRRhLGPBnYA9q3PHpf5ocx7j0~xAbomT~EFX2bzwBu70gKN0qTFVRy8uNu8USYah2YotQH58ChxcEPokhPxENAdNCWeDodsWVFrldbeU0CgVzCrn3MLYu9Ep96r7tjAvKfgQQqC6eORHyM-citVFu1DlJx8-CUN26RQ__',
imageCaption: ''
};
// Fetch and load the HTML component
fetch('components/text-media-2.html')
.then(response => response.text())
.then(data => {
document.getElementById('text-media-2-container').innerHTML = data;
const wrapper = document.querySelector('.text-media-2');
const h3 = document.querySelector('.text-section h3');
const img = document.querySelector('.media-section img');
const imgCaption = document.querySelector('.media-section .image-caption');
// Update content
h3.textContent = config.mainText;
img.src = config.imageUrl;
if (config.imageCaption) {
imgCaption.textContent = config.imageCaption;
img.style.width = '414px';
img.style.height = '624px';
imgCaption.style.display = 'block';
} else {
img.style.width = '414px';
img.style.height = '680px';
imgCaption.style.display = 'none';
}
// Set order
if (config.order === 'text-media') {
wrapper.classList.add('reverse');
}
})
.catch(error => console.error('Error loading text-media-2 component:', error));
});

View File

@@ -0,0 +1,101 @@
.header-container {
text-align: center;
margin-bottom: 40px;
}
.header3 {
align-self: stretch;
color: var(--app-text-stroke-text-stroke-day, #18191E);
text-align: center;
font-family: Montserrat;
font-size: 32px;
font-style: normal;
font-weight: 700;
line-height: 40px;
letter-spacing: -0.64px;
}
.header4 {
align-self: stretch;
color: var(--app-text-stroke-text-stroke-day, #18191E);
text-align: center;
font-family: Montserrat;
font-size: 28px;
font-style: normal;
font-weight: 600;
line-height: 40px;
letter-spacing: -0.56px;
}
.component-instance {
display: flex;
padding: 16px var(--Spacing-Keywords, 0px);
flex-direction: column;
align-items: center;
gap: 16px;
flex: 1 0 0;
text-align: center;
}
.circle-image {
width: 216px;
height: 216px;
border-radius: 50%;
overflow: hidden;
flex-shrink: 0;
}
.circle-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
.component-title {
color: var(--app-text-stroke-text-stroke-day, #18191E);
text-align: center;
font-family: Montserrat;
font-size: 28px;
font-style: normal;
font-weight: 700;
line-height: 40px;
letter-spacing: -0.56px;
margin-bottom: 8px;
}
.component-description {
max-width: 420px;
color: var(--app-text-stroke-text-stroke-day, #18191E);
text-align: center;
font-family: Inter;
font-size: 16px;
font-style: normal;
font-weight: 500;
line-height: 24px;
align-self: center;
}
@media (max-width: 640px) {
.component-instance {
width: 100%;
height: auto;
flex-direction: column;
align-items: center;
gap: 16px;
}
#component-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 40px;
}
.component-instance .circle-image {
margin: 0 auto 16px auto;
}
.component-title {
margin-bottom: 3px;
}
}

View File

@@ -0,0 +1,88 @@
document.addEventListener("DOMContentLoaded", function () {
const componentContainer = document.getElementById('component-container');
const header3 = document.getElementById('header3');
const header4 = document.getElementById('header4');
const showHeader3 = true;
const showHeader4 = true;
if (!showHeader3) {
header3.style.display = 'none';
}
if (!showHeader4) {
header4.style.display = 'none';
}
const componentItems = [
{
imgSrc: 'https://s3-alpha-sig.figma.com/img/76ee/44f2/f217c1ad69179127d1a6a4090d526d86?Expires=1725235200&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=K4KFTc-I4v1fXpSb3eXUkK2kDxJ4hpOVzH6xOyxXXqQCrbew8GjtlOBtRnhihEjtHa2U5N5BfsLyJ4Cvu6K8hW9fyUobMuWuwuWY9~lWEqg-gkTjxSRbxaQVWWrUGsTAFi6-AjqF8PBm3gxandf4JwXTqqydEwYfwPRVb3kTwue5-lDhj4ydmVhO5XXqeqFOQJG4PFIxV7lbCPhqnsCZdB~6uRUkGbFf8HJaqsOKmpnslmtdw237rTlu6VhpQEcs7AKcsIF9N2WI9rnK1OYQdqWz59vbhmYbb0MNuznykLLAINuDFVYU8D958mBrGM1z3zZjVm31ErbnpvzaJarpDQ__',
title: 'Title 1',
description: 'Image Description Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.',
},
{
imgSrc: 'https://s3-alpha-sig.figma.com/img/76ee/44f2/f217c1ad69179127d1a6a4090d526d86?Expires=1725235200&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=K4KFTc-I4v1fXpSb3eXUkK2kDxJ4hpOVzH6xOyxXXqQCrbew8GjtlOBtRnhihEjtHa2U5N5BfsLyJ4Cvu6K8hW9fyUobMuWuwuWY9~lWEqg-gkTjxSRbxaQVWWrUGsTAFi6-AjqF8PBm3gxandf4JwXTqqydEwYfwPRVb3kTwue5-lDhj4ydmVhO5XXqeqFOQJG4PFIxV7lbCPhqnsCZdB~6uRUkGbFf8HJaqsOKmpnslmtdw237rTlu6VhpQEcs7AKcsIF9N2WI9rnK1OYQdqWz59vbhmYbb0MNuznykLLAINuDFVYU8D958mBrGM1z3zZjVm31ErbnpvzaJarpDQ__',
title: 'Title 2',
description: 'Image Description Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.',
},
{
imgSrc: 'https://s3-alpha-sig.figma.com/img/76ee/44f2/f217c1ad69179127d1a6a4090d526d86?Expires=1725235200&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=K4KFTc-I4v1fXpSb3eXUkK2kDxJ4hpOVzH6xOyxXXqQCrbew8GjtlOBtRnhihEjtHa2U5N5BfsLyJ4Cvu6K8hW9fyUobMuWuwuWY9~lWEqg-gkTjxSRbxaQVWWrUGsTAFi6-AjqF8PBm3gxandf4JwXTqqydEwYfwPRVb3kTwue5-lDhj4ydmVhO5XXqeqFOQJG4PFIxV7lbCPhqnsCZdB~6uRUkGbFf8HJaqsOKmpnslmtdw237rTlu6VhpQEcs7AKcsIF9N2WI9rnK1OYQdqWz59vbhmYbb0MNuznykLLAINuDFVYU8D958mBrGM1z3zZjVm31ErbnpvzaJarpDQ__',
title: 'Title 3',
description: 'Image Description Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.',
},
{
imgSrc: 'https://s3-alpha-sig.figma.com/img/76ee/44f2/f217c1ad69179127d1a6a4090d526d86?Expires=1725235200&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=K4KFTc-I4v1fXpSb3eXUkK2kDxJ4hpOVzH6xOyxXXqQCrbew8GjtlOBtRnhihEjtHa2U5N5BfsLyJ4Cvu6K8hW9fyUobMuWuwuWY9~lWEqg-gkTjxSRbxaQVWWrUGsTAFi6-AjqF8PBm3gxandf4JwXTqqydEwYfwPRVb3kTwue5-lDhj4ydmVhO5XXqeqFOQJG4PFIxV7lbCPhqnsCZdB~6uRUkGbFf8HJaqsOKmpnslmtdw237rTlu6VhpQEcs7AKcsIF9N2WI9rnK1OYQdqWz59vbhmYbb0MNuznykLLAINuDFVYU8D958mBrGM1z3zZjVm31ErbnpvzaJarpDQ__',
title: 'Title 3',
description: 'Image Description Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore.',
}
];
const renderComponent = (item) => {
return `
<div class="component-instance">
<div class="circle-image">
<img src="${item.imgSrc}" alt="${item.title}">
</div>
<h3 class="component-title">${item.title}</h3>
<p class="component-description">${item.description}</p>
</div>
`;
};
const applyLayout = () => {
const itemCount = componentItems.length;
componentContainer.innerHTML = '';
let itemWidth, itemHeight;
if (itemCount === 2) {
itemWidth = '508px';
itemHeight = '374px';
componentContainer.className = 'flex justify-center gap-8';
} else if (itemCount === 3) {
itemWidth = '339px';
itemHeight = '398px';
componentContainer.className = 'flex justify-center gap-8';
} else if (itemCount === 4) {
itemWidth = '254px';
itemHeight = '422px';
componentContainer.className = 'flex justify-center gap-8';
} else {
itemWidth = '100%';
itemHeight = 'auto';
componentContainer.className = 'grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8';
}
componentItems.forEach(item => {
const componentHTML = renderComponent(item);
const componentElement = document.createElement('div');
componentElement.innerHTML = componentHTML;
const instance = componentElement.firstElementChild;
instance.style.width = itemWidth;
instance.style.height = itemHeight;
componentContainer.appendChild(instance);
});
};
applyLayout();
});

View File

@@ -0,0 +1,94 @@
.content-container {
max-width: 1200px;
margin: 0 auto;
}
.text-content p {
margin-bottom: 1rem;
}
.single-column .text-content {
max-width: 600px;
margin: 0 auto;
text-indent: 20px;
line-height: 1.6;
}
.two-column .text-content {
column-count: 2;
column-gap: 20px;
line-height: 1.6;
}
.three-column .text-content {
column-count: 3;
column-gap: 20px;
line-height: 1.6;
}
.wide-right-column .text-content {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 20px;
}
.wide-right-column .text-content .left-column {
font-weight: bold;
text-align: justify;
line-height: 1.6;
}
.wide-right-column .text-content .right-column {
font-weight: normal;
text-align: justify;
line-height: 1.6;
}
.optional-header {
margin-bottom: 16px;
}
.optional-header h3 {
font-size: 1.5rem;
font-weight: bold;
margin-bottom: 4px;
}
.optional-header h4 {
font-size: 1.25rem;
font-weight: normal;
color: #555;
}
@media (max-width: 640px) {
.single-column .text-content {
max-width: 100%;
padding: 0 16px;
}
.two-column .text-content,
.three-column .text-content {
column-count: 1;
column-gap: 0;
max-width: 100%;
padding: 0 16px;
}
.wide-right-column .text-content {
display: block;
max-width: 100%;
padding: 0 16px;
}
.wide-right-column .text-content .left-column,
.wide-right-column .text-content .right-column {
margin-bottom: 16px;
text-align: left;
}
.optional-header h3,
.optional-header h4 {
text-align: left;
margin-bottom: 8px;
}
}

View File

@@ -0,0 +1,30 @@
.custom-input {
width: var(--Chart-Module-Width, 325px);
height: 48px;
border-radius: 4px;
border: 1px solid var(--app-input-element-stroke-day, #98A2B3);
background: var(--app-input-element-background-day, #F9FAFB);
color: var(--app-input-text-user-input-day, #1E2024);
text-overflow: ellipsis;
font-family: Inter;
font-size: 16px;
font-weight: 600;
line-height: 24px;
}
.custom-input::placeholder {
color: var(--app-input-text-placeholder-text-day, #7D8188);
font-family: Inter;
font-size: 16px;
font-weight: 400;
line-height: 24px;
}
.error-message {
color: #e53e3e;
display: none;
}
.suggestions-list {
display: none;
}

View File

@@ -0,0 +1,33 @@
<!-- components/textinput.html -->
<template id="textInputTemplate">
<div class="my-4 relative">
<label class="block text-sm font-medium text-gray-700 input-label" style="display: none;"></label>
<div class="mt-1">
<input
type="text"
class="input user-input custom-input"
/>
<button
type="button"
class="absolute right-0 pr-3 flex items-center text-gray-400 clear-button"
style="display: none;"
>
<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
<span
class="absolute right-0 pr-3 flex items-center pointer-events-none status-icon"
style="display: none;"
></span>
<ul class="absolute z-10 w-full suggestions-list" style="display: none;"></ul>
</div>
<p class="text-sm text-gray-500 input-description" style="display: none;"></p>
<p class="text-sm text-red-600 error-message" style="display: none;"></p>
</div>
</template>

View File

@@ -0,0 +1,140 @@
// components/textinput.js
document.addEventListener('DOMContentLoaded', () => {
fetch('components/textinput.html') // Make sure this path is correct
.then(response => response.text())
.then(html => {
document.getElementById('textInputsContainer').innerHTML = html;
initializeComponents();
});
function initializeComponents() {
const textInputTemplate = document.getElementById('textInputTemplate').content;
const container = document.getElementById('textInputsContainer');
const textInputsData = [
{ placeholder: 'Enter your email' } // Example placeholder
];
textInputsData.forEach(data => {
const textInputClone = document.importNode(textInputTemplate, true);
initializeComponent(textInputClone, data);
container.appendChild(textInputClone);
});
function initializeComponent(component, { label, placeholder, description, suggestions = [], error = '' }) {
const userInput = component.querySelector('.user-input');
const clearButton = component.querySelector('.clear-button');
const statusIcon = component.querySelector('.status-icon');
const suggestionsList = component.querySelector('.suggestions-list');
const errorMessage = component.querySelector('.error-message');
const inputLabel = component.querySelector('.input-label');
const inputDescription = component.querySelector('.input-description');
if (label) {
inputLabel.innerText = label;
inputLabel.style.display = 'block';
}
if (placeholder) {
userInput.placeholder = placeholder;
}
if (description) {
inputDescription.innerText = description;
inputDescription.style.display = 'block';
}
userInput.addEventListener('input', (e) => {
const value = e.target.value;
if (value) {
clearButton.style.display = 'flex';
validateInput(value);
if (suggestions.length > 0) {
showSuggestions(value);
}
} else {
clearButton.style.display = 'none';
suggestionsList.style.display = 'none';
removeValidationStyles();
inputDescription.style.display = description ? 'block' : 'none';
}
});
clearButton.addEventListener('click', () => {
userInput.value = '';
clearButton.style.display = 'none';
suggestionsList.style.display = 'none';
removeValidationStyles();
inputDescription.style.display = description ? 'block' : 'none';
});
const showSuggestions = (value) => {
const filteredSuggestions = suggestions.filter(suggestion =>
suggestion.toLowerCase().includes(value.toLowerCase())
);
if (filteredSuggestions.length > 0) {
suggestionsList.innerHTML = '';
filteredSuggestions.forEach(suggestion => {
const listItem = document.createElement('li');
listItem.textContent = suggestion;
listItem.classList.add('px-4', 'py-2', 'cursor-pointer', 'hover:bg-gray-200');
listItem.addEventListener('click', () => {
userInput.value = suggestion;
suggestionsList.style.display = 'none';
clearButton.style.display = 'none';
validateInput(suggestion);
});
suggestionsList.appendChild(listItem);
});
suggestionsList.style.display = 'block';
} else {
suggestionsList.innerHTML = '<li class="px-4 py-2">No results found</li>';
suggestionsList.style.display = 'block';
}
};
const validateInput = (value) => {
removeValidationStyles();
if (value.toLowerCase() === 'error') {
setError('Error description lorem ipsum');
} else {
setValidated();
}
};
const removeValidationStyles = () => {
userInput.classList.remove('input-error', 'input-success');
errorMessage.style.display = 'none';
statusIcon.style.display = 'none';
};
const setError = (error) => {
userInput.classList.add('input-error');
errorMessage.textContent = error;
errorMessage.style.display = 'block';
statusIcon.innerHTML = `
<svg class="h-5 w-5 text-red-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
`;
statusIcon.style.display = 'flex';
};
const setValidated = () => {
userInput.classList.add('input-success');
errorMessage.style.display = 'none';
statusIcon.innerHTML = `
<svg class="h-5 w-5 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
</svg>
`;
statusIcon.style.display = 'flex';
};
if (error) {
setError(error);
}
}
}
});

View File

@@ -0,0 +1,9 @@
<!-- three-column.html -->
<div class="three-column">
<div class="optional-header">
<h3>Headline 3 optional</h3>
<h4>Headline 4 optional</h4>
</div>
<p>Water polo has been part of the Summer Olympics program since the second games, in 1900...</p>
</div>

View File

@@ -0,0 +1,110 @@
.toggle-container {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
width: 130px;
}
.toggle-input {
appearance: none;
width: var(--Card-Radius-L, 32px);
height: var(--Icon-Sizes-Input, 20px);
border-radius: 20px;
position: relative;
cursor: pointer;
flex-shrink: 0;
transition: background-color 0.3s ease, transform 0.3s ease;
}
.toggle-input::before {
content: '';
position: absolute;
width: var(--Icon-Sizes-Input, 20px);
height: var(--Icon-Sizes-Input, 20px);
border-radius: 50%;
top: 0px;
left: 0px;
background-color: white;
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.25);
transition: background-color 0.3s ease, transform 0.3s ease;
fill: var(--smatchit-solid-blue, #0DC3FF);
stroke-width: 1px;
stroke: var(--_app-global-grayscale-50, #F9FAFB);
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
color: transparent;
}
.toggle-input-candidate {
background-color: #ccc;
}
.toggle-input-candidate:checked {
background-color: #B5E7FF;
}
.toggle-input-candidate:checked::before {
transform: translateX(calc(var(--Card-Radius-L, 32px) - var(--Icon-Sizes-Input, 20px)));
background-color: var(--smatchit-solid-blue, #0DC3FF);
color: #F9FAFB !important;
content: '✔';
}
.toggle-input-seeker {
background-color: #E0E0E0;
}
.toggle-input-seeker:checked {
background-color: #F4C4C1;
}
.toggle-input-seeker:checked::before {
transform: translateX(calc(var(--Card-Radius-L, 32px) - var(--Icon-Sizes-Input, 20px)));
background-color: #FA4A64;
color: #F9FAFB !important;
content: '✔';
stroke: #F9FAFB;
}
.toggle-label {
display: flex;
align-items: center;
cursor: pointer;
flex: 1 0 0;
color: var(--app-input-text-label-day, #1E2024);
font-family: Inter, sans-serif;
font-size: 14px;
font-style: normal;
font-weight: 500;
line-height: 20px;
gap: var(--Input-Element-Radius-CTA-M, 1.5px);
}
.toggle-icon {
margin-right: 0.5rem;
}
.toggle-label-left {
display: flex;
align-items: center;
justify-content: flex-start;
}
.toggle-label-left .toggle-input {
order: 1;
margin-right: auto;
}
.toggle-label-right {
display: flex;
align-items: center;
justify-content: flex-end;
}
.toggle-label-right .toggle-input {
order: 2;
margin-left: auto;
}

View File

@@ -0,0 +1,51 @@
const toggleData = [
{ label: 'Option 1', position: 'right', type: 'candidate' },
{ label: 'Option 2', icon: '📞', position: 'right', type: 'seeker' },
{ label: 'Option 3', icon: '📞', position: 'left', type: 'candidate' },
{ label: 'Option 4', icon: '📞', position: 'left', type: 'seeker' },
];
function createToggleComponent({ label, icon, position, type }) {
const toggleContainer = document.createElement('div');
toggleContainer.className = `toggle-container`;
const toggleInput = document.createElement('input');
toggleInput.type = 'checkbox';
toggleInput.className = `toggle-input toggle-input-${type}`;
toggleInput.id = label;
const toggleLabel = document.createElement('label');
toggleLabel.className = `toggle-label toggle-label-${position}`;
toggleLabel.htmlFor = label;
if (icon) {
const iconElement = document.createElement('span');
iconElement.className = 'toggle-icon';
iconElement.innerText = icon;
toggleLabel.appendChild(iconElement);
}
if (label) {
const labelText = document.createElement('span');
labelText.innerText = label;
toggleLabel.appendChild(labelText);
}
if (position === 'left') {
toggleContainer.appendChild(toggleLabel);
toggleContainer.appendChild(toggleInput);
} else {
toggleContainer.appendChild(toggleInput);
toggleContainer.appendChild(toggleLabel);
}
return toggleContainer;
}
document.addEventListener('DOMContentLoaded', () => {
const toggleContainer = document.getElementById('toggle-container');
toggleData.forEach(toggleConfig => {
const toggleComponent = createToggleComponent(toggleConfig);
toggleContainer.appendChild(toggleComponent);
});
});

View File

@@ -0,0 +1,71 @@
.trio-layout {
display: flex;
flex-direction: row;
gap: 16px;
justify-content: center;
flex-wrap: wrap;
}
.trio-layout .left-column {
width: 500px;
height: 720px;
flex-shrink: 0;
overflow: hidden;
}
.trio-layout .right-column {
display: flex;
flex-direction: column;
gap: 16px;
}
.trio-layout .right-column .media-item {
width: 500px;
height: 352px;
flex-shrink: 0;
overflow: hidden;
}
.trio-layout .media-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
@media (max-width: 768px) {
.trio-layout {
flex-direction: row;
gap: 8px;
justify-content: center;
padding: 0 8px;
flex-wrap: nowrap;
}
.trio-layout .left-column {
width: 60%;
height: auto;
display: flex;
align-items: stretch;
}
.trio-layout .right-column {
width: 40%;
display: flex;
flex-direction: column;
gap: 8px;
justify-content: space-between;
height: 100%;
}
.trio-layout .right-column .media-item {
width: 100%;
height: 50%;
overflow: hidden;
}
.trio-layout .media-item img {
width: 100%;
height: 100%;
object-fit: cover;
}
}

View File

@@ -0,0 +1,9 @@
<!-- two-column.html -->
<div class="two-column">
<div class="optional-header">
<h3>Headline 3 optional</h3>
<h4>Headline 4 optional</h4>
</div>
<p>Water polo has been part of the Summer Olympics program since the second games, in 1900...</p>
</div>

View File

@@ -0,0 +1,14 @@
<!-- wide-right-column.html -->
<div class="wide-right-column">
<div class="optional-header">
<h3>Headline 3 optional</h3>
<h4>Headline 4 optional</h4>
</div>
<div class="left-column">
Water polo has been part of the Summer Olympics program since the second games, in 1900...
</div>
<div class="right-column">
Italy is the first and only country to win both the men's and women's water polo tournaments...
</div>
</div>

View File

@@ -0,0 +1,3 @@
<div id="wrapper-media-layout" class="max-w-screen-lg mx-auto mb-8">
<div id="media-container"></div>
</div>

View File

@@ -0,0 +1,128 @@
/*
//start with if need a google font
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
*/
@font-face{
font-family: 'Questrial';
/*font-style: normal;
font-weight: 400;*/
font-display: swap;
src: url(../fonts/questrial-regular-webfont.woff2) format('woff2');
}
@font-face{
font-family:'Quicksand';
/*font-style: normal;
font-weight: 400;*/
font-display: swap;
src: url(../fonts/Quicksand-Light.ttf) format('ttf');
}
@import "tailwindcss" source("../../../src/**/*.{html,js,mustache}");
@import "./sourcetw.css";
@plugin "daisyui";
@theme {
--font-display: "Questrial", "sans-serif";
--font-display--font-feature-settings: "cv02", "cv03", "cv04", "cv11";
--font-display--font-variation-settings: "opsz" 32;
--font-heading:"Quicksand","system-ui";
--font-body:"Questrial";
}
@layer base {
html {
font-family: var(--font-body);
font-weight: 300; /* Si nécessaire */
}
h1, h2, h3, h4, h5, h6 {
font-family: var(--font-heading);
font-weight: 500; /* Ajuster selon besoin */
}
}
@plugin "daisyui/theme" {
name: "apxtridark";
default: true;
prefersdark: true;
color-scheme: "dark";
--color-base-100: oklch(40% 0.016 252.42);
--color-base-200: oklch(20% 0.014 253.1);
--color-base-300: oklch(15% 0.012 254.09);
--color-base-content: oklch(97.807% 0.029 256.847);
--color-primary: oklch(58.34% 0.136 249.54);
--color-primary-content: oklch(96% 0.018 272.314);
--color-secondary: oklch(69.54% 0.189 40.23);
--color-secondary-content: oklch(94% 0.028 342.258);
--color-accent: oklch(77% 0.152 181.912);
--color-accent-content: oklch(38% 0.063 188.416);
--color-neutral: oklch(14% 0.005 285.823);
--color-neutral-content: oklch(92% 0.004 286.32);
--color-info: oklch(56.86% 0.088 194.95);
--color-info-content: oklch(29% 0.066 243.157);
--color-success: oklch(66.88% 0.138 137.06);
--color-success-content: oklch(37% 0.077 168.94);
--color-warning: oklch(84.93% 0.162 84.01);
--color-warning-content: oklch(41% 0.112 45.904);
--color-error: oklch(71% 0.194 13.428);
--color-error-content: oklch(14% 0.004 49.25);
--radius-selector: 0.25rem;
--radius-field: 0.5rem;
--radius-box: 0.5rem;
--size-selector: 0.25rem;
--size-field: 0.28125rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
@plugin "daisyui/theme" {
name: "apxtrilight";
default: false;
prefersdark: false;
color-scheme: "light";
--color-base-100: oklch(100% 0 0);
--color-base-200: oklch(98% 0 0);
--color-base-300: oklch(95% 0 0);
--color-base-content: oklch(21% 0.006 285.885);
--color-primary: oklch(58.34% 0.136 249.54);
--color-primary-content: oklch(93% 0.034 272.788);
--color-secondary: oklch(69.54% 0.189 40.23);
--color-secondary-content: oklch(94% 0.028 342.258);
--color-accent: oklch(84.93% 0.162 84.01);
--color-accent-content: oklch(21% 0.006 285.885);
--color-neutral: oklch(7% 0.006 286.033);
--color-neutral-content: oklch(1% 0.004 286.32);
--color-info: oklch(56.86% 0.088 194.95);
--color-info-content: oklch(98% 0 0);
--color-success: oklch(66.88% 0.138 137.06);
--color-success-content: oklch(92% 0.004 286.32);
--color-warning: oklch(84.93% 0.162 84.01);
--color-warning-content: oklch(41% 0.112 45.904);
--color-error: oklch(71% 0.194 13.428);
--color-error-content: oklch(27% 0.105 12.094);
--radius-selector: 0.5rem;
--radius-field: 0.25rem;
--radius-box: 0.5rem;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 1;
--noise: 0;
}
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #2d3748;
}
::-webkit-scrollbar-thumb {
background: #4a5568;
border-radius: 4px;
}
.transition-width {
transition: width 0.3s ease;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
@source "../../../../../../../apxtri/objects/wco/apx/*.{html,js,mustache}";
@source "../../../../../../../apxtri/objects/wwws/admin/src/**/*.{html,js,mustache}";
@source "../../../../../../../apxtri/objects/wco/simplemobnav/*.{html,js,mustache}";
@source "../../../../../../../apxtri/objects/wco/apxauth/*.{html,js,mustache}";
@source "../../../../../../../apxtri/objects/wco/adminskull/*.{html,js,mustache}";

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,12 @@
var apx = apx || {};
apx.adminsearch = (search) => {
// do search depending of project and rules
console.log(search)
search.results = [
{ thumbnail:"", title: "Res1", description: "blablaresultat1" },
{ thumbnail:"", title: "Res2", description: "blablaresultat2" },
{ thumbnail:"", title: "Res3", description: "blablaresultat3" },
];
return search;
};

View File

@@ -0,0 +1,196 @@
apx=apx|| {}
apx.testapi={}
apx.testapi.runtest = async () => {
apx.testapi.updatepersonbio();
//apx.testapi.testupdatskills()
//apx.testapi.testseekeronboardingmatching("aams");
/* const jobstepstodo = await axios.put(
`/api/smatchit/jobads/jobstepstodo/bhavesh_78731a7e-61a5-489c-8b3b-2cddcf13f127_1`,
{"state":"booked","slottime":{"date":"2024-10-23","start":"15:30","numberofslot":1}} ,
{ headers: apx.data.headers }
);
console.log(jobstepstodo);
*/
};
apx.testapi.testseekeronboardingmatching = async (seeker) => {
await axios
.get(`/api/smatchit/seekers/onboarding/${seeker}`, {
headers: apx.data.headers,
})
.then((rep) => {
//alert("success, check console");
console.log(rep);
})
.catch((err) => {
//alert("err, check console");
console.log(err);
});
};
apx.testapi.testupdatskills = async () => {
const data = {
alias: "philc3",
owner: "philc3",
dt_create: "2024-12-10T09:45:49.901Z",
email: "phc@ndda.fr",
seekstatus: "startasap",
seekworkingyear: "1to3",
seekjobtitleexperience: ["vente1n1"],
seeklocation: [
{
type: "street",
housenumber: "",
street: "Igny",
name: "Igny",
label: "Igny 18200 La Perche",
postcode: "18200",
citycode: "18178",
city: "La Perche",
zoning: 3,
position: {
longitude: 2.585915,
latitude: 46.638536,
},
context: "18, Cher, Centre-Val de Loire",
},
],
salaryexpectation: 11111,
salarydevise: "€",
salaryunit: "peryear",
seekjobtype: [],
mbti: {
E: 1,
S: 2,
T: 1,
J: 1,
nextq: 4,
value: "INFP",
},
countryavailabletowork: [],
lastlocation: {},
tipsadvice: [
"f46b2d7e-e242-421f-802b-d8d4d02ab123",
"f46b2d7e-e242-421f-802b-d8d4d02ab124",
],
mywords: ["Réfléchi(e)", "Visionnaire", "Empathique", "Flexible"],
myworkexperience: [],
lookingforaction: [
"À la recherche d'une opportunité professionnelle dans :",
],
lookingforother: ["vente"],
myjobradar: ["vente1n1"],
skills: {
promoteoffer: 4,
orientclient: 2,
qualitycontrol: 2,
manageadm: 2,
doinvoice: 2,
followsells: 2,
makereservation: 2,
},
languageskills: {
french: 4,
english: 2,
},
knowhow: {},
jobadview: [],
jobadapply: [],
jobadinvitedtoapply: [],
jobadsaved: [],
jobadofferaccepted: [],
jobadprocessstopseeker: [],
jobadprocessstoprecruiter: [],
jobadnotinterested: [],
jobadmatchscore: [
{
jobadid: "0f7a4468-7d35-47a8-acc0-39b30220b67b",
score: 25,
newmatch: true,
aboutyou: "",
criteria: ["Salaire", "Localisation"],
whyworkhere:
"Aie un impact tous les jours\nPar nos actions, nous aidons nos clients à avoir un impact sur la société. Venez nous rejoindre pour faire partie de cette aventure !",
distanceseekerjob: 247.2,
currentlyinprocess: false,
},
{
jobadid: "98ec1cd8-ea53-4509-a3dc-3fabfe9134d9",
score: 20,
newmatch: true,
aboutyou: "",
criteria: ["Salaire", "Localisation"],
whyworkhere: "",
distanceseekerjob: 246.9,
currentlyinprocess: false,
},
{
jobadid: "5c77eed3-5fe5-4a0e-84cb-b2f5672298d1",
score: 16,
newmatch: true,
aboutyou: "Describe here your ideal candidate for this job",
criteria: ["Salaire", "Localisation"],
whyworkhere: "",
distanceseekerjob: 486.7,
currentlyinprocess: false,
},
{
jobadid: "cc23a1a9-be59-4589-8c7f-916eb41413c8",
score: 12,
newmatch: true,
aboutyou: "Description du candidat idéal pour ce poste",
criteria: [
"Salaire",
"Localisation",
"La mission est adaptée pour vous",
],
whyworkhere: "",
distanceseekerjob: 254.1,
currentlyinprocess: false,
},
{
jobadid: "b8af608c-0199-4814-af42-084fd0d5715f",
score: 12,
newmatch: true,
aboutyou: "",
criteria: [
"Salaire",
"Localisation",
"La mission est adaptée pour vous",
],
whyworkhere: "",
distanceseekerjob: 395.5,
currentlyinprocess: false,
},
],
jobstepstodo: [],
jobstepsdone: [],
educations: [],
recommandation: [],
employmentstatus: "employed",
};
await axios
.put("/api/apxtri/odmdb/itm/smatchit/seekers", data, {
headers: apx.data.headers,
})
.then((rep) => {
console.log(rep);
})
.catch((err) => {
console.log(err);
});
};
apx.testapi.updatepersonbio = async () => {
const data = { alias: "philc3", biography: "Lorem ipsum ...." };
await axios
.put("/api/apxtri/odmdb/itm/smatchit/persons", data, {
headers: apx.data.headers,
})
.then((rep) => {
console.log(rep);
})
.catch((err) => {
console.log(err);
});
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,344 @@
/* BASICS */
.CodeMirror {
/* Set height, width, borders, and global font properties here */
font-family: monospace;
height: 300px;
color: black;
direction: ltr;
}
/* PADDING */
.CodeMirror-lines {
padding: 4px 0; /* Vertical padding around content */
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
padding: 0 4px; /* Horizontal padding of content */
}
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
background-color: white; /* The little square between H and V scrollbars */
}
/* GUTTER */
.CodeMirror-gutters {
border-right: 1px solid #ddd;
background-color: #f7f7f7;
white-space: nowrap;
}
.CodeMirror-linenumbers {}
.CodeMirror-linenumber {
padding: 0 3px 0 5px;
min-width: 20px;
text-align: right;
color: #999;
white-space: nowrap;
}
.CodeMirror-guttermarker { color: black; }
.CodeMirror-guttermarker-subtle { color: #999; }
/* CURSOR */
.CodeMirror-cursor {
border-left: 1px solid black;
border-right: none;
width: 0;
}
/* Shown when moving in bi-directional text */
.CodeMirror div.CodeMirror-secondarycursor {
border-left: 1px solid silver;
}
.cm-fat-cursor .CodeMirror-cursor {
width: auto;
border: 0 !important;
background: #7e7;
}
.cm-fat-cursor div.CodeMirror-cursors {
z-index: 1;
}
.cm-fat-cursor .CodeMirror-line::selection,
.cm-fat-cursor .CodeMirror-line > span::selection,
.cm-fat-cursor .CodeMirror-line > span > span::selection { background: transparent; }
.cm-fat-cursor .CodeMirror-line::-moz-selection,
.cm-fat-cursor .CodeMirror-line > span::-moz-selection,
.cm-fat-cursor .CodeMirror-line > span > span::-moz-selection { background: transparent; }
.cm-fat-cursor { caret-color: transparent; }
@-moz-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@-webkit-keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
@keyframes blink {
0% {}
50% { background-color: transparent; }
100% {}
}
/* Can style cursor different in overwrite (non-insert) mode */
.CodeMirror-overwrite .CodeMirror-cursor {}
.cm-tab { display: inline-block; text-decoration: inherit; }
.CodeMirror-rulers {
position: absolute;
left: 0; right: 0; top: -50px; bottom: 0;
overflow: hidden;
}
.CodeMirror-ruler {
border-left: 1px solid #ccc;
top: 0; bottom: 0;
position: absolute;
}
/* DEFAULT THEME */
.cm-s-default .cm-header {color: blue;}
.cm-s-default .cm-quote {color: #090;}
.cm-negative {color: #d44;}
.cm-positive {color: #292;}
.cm-header, .cm-strong {font-weight: bold;}
.cm-em {font-style: italic;}
.cm-link {text-decoration: underline;}
.cm-strikethrough {text-decoration: line-through;}
.cm-s-default .cm-keyword {color: #708;}
.cm-s-default .cm-atom {color: #219;}
.cm-s-default .cm-number {color: #164;}
.cm-s-default .cm-def {color: #00f;}
.cm-s-default .cm-variable,
.cm-s-default .cm-punctuation,
.cm-s-default .cm-property,
.cm-s-default .cm-operator {}
.cm-s-default .cm-variable-2 {color: #05a;}
.cm-s-default .cm-variable-3, .cm-s-default .cm-type {color: #085;}
.cm-s-default .cm-comment {color: #a50;}
.cm-s-default .cm-string {color: #a11;}
.cm-s-default .cm-string-2 {color: #f50;}
.cm-s-default .cm-meta {color: #555;}
.cm-s-default .cm-qualifier {color: #555;}
.cm-s-default .cm-builtin {color: #30a;}
.cm-s-default .cm-bracket {color: #997;}
.cm-s-default .cm-tag {color: #170;}
.cm-s-default .cm-attribute {color: #00c;}
.cm-s-default .cm-hr {color: #999;}
.cm-s-default .cm-link {color: #00c;}
.cm-s-default .cm-error {color: #f00;}
.cm-invalidchar {color: #f00;}
.CodeMirror-composing { border-bottom: 2px solid; }
/* Default styles for common addons */
div.CodeMirror span.CodeMirror-matchingbracket {color: #0b0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
.CodeMirror-matchingtag { background: rgba(255, 150, 0, .3); }
.CodeMirror-activeline-background {background: #e8f2ff;}
/* STOP */
/* The rest of this file contains styles related to the mechanics of
the editor. You probably shouldn't touch them. */
.CodeMirror {
position: relative;
overflow: hidden;
background: white;
}
.CodeMirror-scroll {
overflow: scroll !important; /* Things will break if this is overridden */
/* 50px is the magic margin used to hide the element's real scrollbars */
/* See overflow: hidden in .CodeMirror */
margin-bottom: -50px; margin-right: -50px;
padding-bottom: 50px;
height: 100%;
outline: none; /* Prevent dragging from highlighting the element */
position: relative;
z-index: 0;
}
.CodeMirror-sizer {
position: relative;
border-right: 50px solid transparent;
}
/* The fake, visible scrollbars. Used to force redraw during scrolling
before actual scrolling happens, thus preventing shaking and
flickering artifacts. */
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler {
position: absolute;
z-index: 6;
display: none;
outline: none;
}
.CodeMirror-vscrollbar {
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
}
.CodeMirror-hscrollbar {
bottom: 0; left: 0;
overflow-y: hidden;
overflow-x: scroll;
}
.CodeMirror-scrollbar-filler {
right: 0; bottom: 0;
}
.CodeMirror-gutter-filler {
left: 0; bottom: 0;
}
.CodeMirror-gutters {
position: absolute; left: 0; top: 0;
min-height: 100%;
z-index: 3;
}
.CodeMirror-gutter {
white-space: normal;
height: 100%;
display: inline-block;
vertical-align: top;
margin-bottom: -50px;
}
.CodeMirror-gutter-wrapper {
position: absolute;
z-index: 4;
background: none !important;
border: none !important;
}
.CodeMirror-gutter-background {
position: absolute;
top: 0; bottom: 0;
z-index: 4;
}
.CodeMirror-gutter-elt {
position: absolute;
cursor: default;
z-index: 4;
}
.CodeMirror-gutter-wrapper ::selection { background-color: transparent }
.CodeMirror-gutter-wrapper ::-moz-selection { background-color: transparent }
.CodeMirror-lines {
cursor: text;
min-height: 1px; /* prevents collapsing before first draw */
}
.CodeMirror pre.CodeMirror-line,
.CodeMirror pre.CodeMirror-line-like {
/* Reset some styles that the rest of the page might have set */
-moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0;
border-width: 0;
background: transparent;
font-family: inherit;
font-size: inherit;
margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
z-index: 2;
position: relative;
overflow: visible;
-webkit-tap-highlight-color: transparent;
-webkit-font-variant-ligatures: contextual;
font-variant-ligatures: contextual;
}
.CodeMirror-wrap pre.CodeMirror-line,
.CodeMirror-wrap pre.CodeMirror-line-like {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-linebackground {
position: absolute;
left: 0; right: 0; top: 0; bottom: 0;
z-index: 0;
}
.CodeMirror-linewidget {
position: relative;
z-index: 2;
padding: 0.1px; /* Force widget margins to stay inside of the container */
}
.CodeMirror-widget {}
.CodeMirror-rtl pre { direction: rtl; }
.CodeMirror-code {
outline: none;
}
/* Force content-box sizing for the elements where we expect it */
.CodeMirror-scroll,
.CodeMirror-sizer,
.CodeMirror-gutter,
.CodeMirror-gutters,
.CodeMirror-linenumber {
-moz-box-sizing: content-box;
box-sizing: content-box;
}
.CodeMirror-measure {
position: absolute;
width: 100%;
height: 0;
overflow: hidden;
visibility: hidden;
}
.CodeMirror-cursor {
position: absolute;
pointer-events: none;
}
.CodeMirror-measure pre { position: static; }
div.CodeMirror-cursors {
visibility: hidden;
position: relative;
z-index: 3;
}
div.CodeMirror-dragcursors {
visibility: visible;
}
.CodeMirror-focused div.CodeMirror-cursors {
visibility: visible;
}
.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused .CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-crosshair { cursor: crosshair; }
.CodeMirror-line::selection, .CodeMirror-line > span::selection, .CodeMirror-line > span > span::selection { background: #d7d4f0; }
.CodeMirror-line::-moz-selection, .CodeMirror-line > span::-moz-selection, .CodeMirror-line > span > span::-moz-selection { background: #d7d4f0; }
.cm-searching {
background-color: #ffa;
background-color: rgba(255, 255, 0, .4);
}
/* Used to force a border model for a node */
.cm-force-border { padding-right: .1px; }
@media print {
/* Hide the cursor when printing */
.CodeMirror div.CodeMirror-cursors {
visibility: hidden;
}
}
/* See issue #2901 */
.cm-tab-wrap-hack:after { content: ''; }
/* Help users use markselection to safely style text background */
span.CodeMirror-selectedtext { background: none; }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,862 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineMode("css", function(config, parserConfig) {
var inline = parserConfig.inline
if (!parserConfig.propertyKeywords) parserConfig = CodeMirror.resolveMode("text/css");
var indentUnit = config.indentUnit,
tokenHooks = parserConfig.tokenHooks,
documentTypes = parserConfig.documentTypes || {},
mediaTypes = parserConfig.mediaTypes || {},
mediaFeatures = parserConfig.mediaFeatures || {},
mediaValueKeywords = parserConfig.mediaValueKeywords || {},
propertyKeywords = parserConfig.propertyKeywords || {},
nonStandardPropertyKeywords = parserConfig.nonStandardPropertyKeywords || {},
fontProperties = parserConfig.fontProperties || {},
counterDescriptors = parserConfig.counterDescriptors || {},
colorKeywords = parserConfig.colorKeywords || {},
valueKeywords = parserConfig.valueKeywords || {},
allowNested = parserConfig.allowNested,
lineComment = parserConfig.lineComment,
supportsAtComponent = parserConfig.supportsAtComponent === true,
highlightNonStandardPropertyKeywords = config.highlightNonStandardPropertyKeywords !== false;
var type, override;
function ret(style, tp) { type = tp; return style; }
// Tokenizers
function tokenBase(stream, state) {
var ch = stream.next();
if (tokenHooks[ch]) {
var result = tokenHooks[ch](stream, state);
if (result !== false) return result;
}
if (ch == "@") {
stream.eatWhile(/[\w\\\-]/);
return ret("def", stream.current());
} else if (ch == "=" || (ch == "~" || ch == "|") && stream.eat("=")) {
return ret(null, "compare");
} else if (ch == "\"" || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
} else if (ch == "#") {
stream.eatWhile(/[\w\\\-]/);
return ret("atom", "hash");
} else if (ch == "!") {
stream.match(/^\s*\w*/);
return ret("keyword", "important");
} else if (/\d/.test(ch) || ch == "." && stream.eat(/\d/)) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
} else if (ch === "-") {
if (/[\d.]/.test(stream.peek())) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
} else if (stream.match(/^-[\w\\\-]*/)) {
stream.eatWhile(/[\w\\\-]/);
if (stream.match(/^\s*:/, false))
return ret("variable-2", "variable-definition");
return ret("variable-2", "variable");
} else if (stream.match(/^\w+-/)) {
return ret("meta", "meta");
}
} else if (/[,+>*\/]/.test(ch)) {
return ret(null, "select-op");
} else if (ch == "." && stream.match(/^-?[_a-z][_a-z0-9-]*/i)) {
return ret("qualifier", "qualifier");
} else if (/[:;{}\[\]\(\)]/.test(ch)) {
return ret(null, ch);
} else if (stream.match(/^[\w-.]+(?=\()/)) {
if (/^(url(-prefix)?|domain|regexp)$/i.test(stream.current())) {
state.tokenize = tokenParenthesized;
}
return ret("variable callee", "variable");
} else if (/[\w\\\-]/.test(ch)) {
stream.eatWhile(/[\w\\\-]/);
return ret("property", "word");
} else {
return ret(null, null);
}
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, ch;
while ((ch = stream.next()) != null) {
if (ch == quote && !escaped) {
if (quote == ")") stream.backUp(1);
break;
}
escaped = !escaped && ch == "\\";
}
if (ch == quote || !escaped && quote != ")") state.tokenize = null;
return ret("string", "string");
};
}
function tokenParenthesized(stream, state) {
stream.next(); // Must be '('
if (!stream.match(/^\s*[\"\')]/, false))
state.tokenize = tokenString(")");
else
state.tokenize = null;
return ret(null, "(");
}
// Context management
function Context(type, indent, prev) {
this.type = type;
this.indent = indent;
this.prev = prev;
}
function pushContext(state, stream, type, indent) {
state.context = new Context(type, stream.indentation() + (indent === false ? 0 : indentUnit), state.context);
return type;
}
function popContext(state) {
if (state.context.prev)
state.context = state.context.prev;
return state.context.type;
}
function pass(type, stream, state) {
return states[state.context.type](type, stream, state);
}
function popAndPass(type, stream, state, n) {
for (var i = n || 1; i > 0; i--)
state.context = state.context.prev;
return pass(type, stream, state);
}
// Parser
function wordAsValue(stream) {
var word = stream.current().toLowerCase();
if (valueKeywords.hasOwnProperty(word))
override = "atom";
else if (colorKeywords.hasOwnProperty(word))
override = "keyword";
else
override = "variable";
}
var states = {};
states.top = function(type, stream, state) {
if (type == "{") {
return pushContext(state, stream, "block");
} else if (type == "}" && state.context.prev) {
return popContext(state);
} else if (supportsAtComponent && /@component/i.test(type)) {
return pushContext(state, stream, "atComponentBlock");
} else if (/^@(-moz-)?document$/i.test(type)) {
return pushContext(state, stream, "documentTypes");
} else if (/^@(media|supports|(-moz-)?document|import)$/i.test(type)) {
return pushContext(state, stream, "atBlock");
} else if (/^@(font-face|counter-style)/i.test(type)) {
state.stateArg = type;
return "restricted_atBlock_before";
} else if (/^@(-(moz|ms|o|webkit)-)?keyframes$/i.test(type)) {
return "keyframes";
} else if (type && type.charAt(0) == "@") {
return pushContext(state, stream, "at");
} else if (type == "hash") {
override = "builtin";
} else if (type == "word") {
override = "tag";
} else if (type == "variable-definition") {
return "maybeprop";
} else if (type == "interpolation") {
return pushContext(state, stream, "interpolation");
} else if (type == ":") {
return "pseudo";
} else if (allowNested && type == "(") {
return pushContext(state, stream, "parens");
}
return state.context.type;
};
states.block = function(type, stream, state) {
if (type == "word") {
var word = stream.current().toLowerCase();
if (propertyKeywords.hasOwnProperty(word)) {
override = "property";
return "maybeprop";
} else if (nonStandardPropertyKeywords.hasOwnProperty(word)) {
override = highlightNonStandardPropertyKeywords ? "string-2" : "property";
return "maybeprop";
} else if (allowNested) {
override = stream.match(/^\s*:(?:\s|$)/, false) ? "property" : "tag";
return "block";
} else {
override += " error";
return "maybeprop";
}
} else if (type == "meta") {
return "block";
} else if (!allowNested && (type == "hash" || type == "qualifier")) {
override = "error";
return "block";
} else {
return states.top(type, stream, state);
}
};
states.maybeprop = function(type, stream, state) {
if (type == ":") return pushContext(state, stream, "prop");
return pass(type, stream, state);
};
states.prop = function(type, stream, state) {
if (type == ";") return popContext(state);
if (type == "{" && allowNested) return pushContext(state, stream, "propBlock");
if (type == "}" || type == "{") return popAndPass(type, stream, state);
if (type == "(") return pushContext(state, stream, "parens");
if (type == "hash" && !/^#([0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(stream.current())) {
override += " error";
} else if (type == "word") {
wordAsValue(stream);
} else if (type == "interpolation") {
return pushContext(state, stream, "interpolation");
}
return "prop";
};
states.propBlock = function(type, _stream, state) {
if (type == "}") return popContext(state);
if (type == "word") { override = "property"; return "maybeprop"; }
return state.context.type;
};
states.parens = function(type, stream, state) {
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == ")") return popContext(state);
if (type == "(") return pushContext(state, stream, "parens");
if (type == "interpolation") return pushContext(state, stream, "interpolation");
if (type == "word") wordAsValue(stream);
return "parens";
};
states.pseudo = function(type, stream, state) {
if (type == "meta") return "pseudo";
if (type == "word") {
override = "variable-3";
return state.context.type;
}
return pass(type, stream, state);
};
states.documentTypes = function(type, stream, state) {
if (type == "word" && documentTypes.hasOwnProperty(stream.current())) {
override = "tag";
return state.context.type;
} else {
return states.atBlock(type, stream, state);
}
};
states.atBlock = function(type, stream, state) {
if (type == "(") return pushContext(state, stream, "atBlock_parens");
if (type == "}" || type == ";") return popAndPass(type, stream, state);
if (type == "{") return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top");
if (type == "interpolation") return pushContext(state, stream, "interpolation");
if (type == "word") {
var word = stream.current().toLowerCase();
if (word == "only" || word == "not" || word == "and" || word == "or")
override = "keyword";
else if (mediaTypes.hasOwnProperty(word))
override = "attribute";
else if (mediaFeatures.hasOwnProperty(word))
override = "property";
else if (mediaValueKeywords.hasOwnProperty(word))
override = "keyword";
else if (propertyKeywords.hasOwnProperty(word))
override = "property";
else if (nonStandardPropertyKeywords.hasOwnProperty(word))
override = highlightNonStandardPropertyKeywords ? "string-2" : "property";
else if (valueKeywords.hasOwnProperty(word))
override = "atom";
else if (colorKeywords.hasOwnProperty(word))
override = "keyword";
else
override = "error";
}
return state.context.type;
};
states.atComponentBlock = function(type, stream, state) {
if (type == "}")
return popAndPass(type, stream, state);
if (type == "{")
return popContext(state) && pushContext(state, stream, allowNested ? "block" : "top", false);
if (type == "word")
override = "error";
return state.context.type;
};
states.atBlock_parens = function(type, stream, state) {
if (type == ")") return popContext(state);
if (type == "{" || type == "}") return popAndPass(type, stream, state, 2);
return states.atBlock(type, stream, state);
};
states.restricted_atBlock_before = function(type, stream, state) {
if (type == "{")
return pushContext(state, stream, "restricted_atBlock");
if (type == "word" && state.stateArg == "@counter-style") {
override = "variable";
return "restricted_atBlock_before";
}
return pass(type, stream, state);
};
states.restricted_atBlock = function(type, stream, state) {
if (type == "}") {
state.stateArg = null;
return popContext(state);
}
if (type == "word") {
if ((state.stateArg == "@font-face" && !fontProperties.hasOwnProperty(stream.current().toLowerCase())) ||
(state.stateArg == "@counter-style" && !counterDescriptors.hasOwnProperty(stream.current().toLowerCase())))
override = "error";
else
override = "property";
return "maybeprop";
}
return "restricted_atBlock";
};
states.keyframes = function(type, stream, state) {
if (type == "word") { override = "variable"; return "keyframes"; }
if (type == "{") return pushContext(state, stream, "top");
return pass(type, stream, state);
};
states.at = function(type, stream, state) {
if (type == ";") return popContext(state);
if (type == "{" || type == "}") return popAndPass(type, stream, state);
if (type == "word") override = "tag";
else if (type == "hash") override = "builtin";
return "at";
};
states.interpolation = function(type, stream, state) {
if (type == "}") return popContext(state);
if (type == "{" || type == ";") return popAndPass(type, stream, state);
if (type == "word") override = "variable";
else if (type != "variable" && type != "(" && type != ")") override = "error";
return "interpolation";
};
return {
startState: function(base) {
return {tokenize: null,
state: inline ? "block" : "top",
stateArg: null,
context: new Context(inline ? "block" : "top", base || 0, null)};
},
token: function(stream, state) {
if (!state.tokenize && stream.eatSpace()) return null;
var style = (state.tokenize || tokenBase)(stream, state);
if (style && typeof style == "object") {
type = style[1];
style = style[0];
}
override = style;
if (type != "comment")
state.state = states[state.state](type, stream, state);
return override;
},
indent: function(state, textAfter) {
var cx = state.context, ch = textAfter && textAfter.charAt(0);
var indent = cx.indent;
if (cx.type == "prop" && (ch == "}" || ch == ")")) cx = cx.prev;
if (cx.prev) {
if (ch == "}" && (cx.type == "block" || cx.type == "top" ||
cx.type == "interpolation" || cx.type == "restricted_atBlock")) {
// Resume indentation from parent context.
cx = cx.prev;
indent = cx.indent;
} else if (ch == ")" && (cx.type == "parens" || cx.type == "atBlock_parens") ||
ch == "{" && (cx.type == "at" || cx.type == "atBlock")) {
// Dedent relative to current context.
indent = Math.max(0, cx.indent - indentUnit);
}
}
return indent;
},
electricChars: "}",
blockCommentStart: "/*",
blockCommentEnd: "*/",
blockCommentContinue: " * ",
lineComment: lineComment,
fold: "brace"
};
});
function keySet(array) {
var keys = {};
for (var i = 0; i < array.length; ++i) {
keys[array[i].toLowerCase()] = true;
}
return keys;
}
var documentTypes_ = [
"domain", "regexp", "url", "url-prefix"
], documentTypes = keySet(documentTypes_);
var mediaTypes_ = [
"all", "aural", "braille", "handheld", "print", "projection", "screen",
"tty", "tv", "embossed"
], mediaTypes = keySet(mediaTypes_);
var mediaFeatures_ = [
"width", "min-width", "max-width", "height", "min-height", "max-height",
"device-width", "min-device-width", "max-device-width", "device-height",
"min-device-height", "max-device-height", "aspect-ratio",
"min-aspect-ratio", "max-aspect-ratio", "device-aspect-ratio",
"min-device-aspect-ratio", "max-device-aspect-ratio", "color", "min-color",
"max-color", "color-index", "min-color-index", "max-color-index",
"monochrome", "min-monochrome", "max-monochrome", "resolution",
"min-resolution", "max-resolution", "scan", "grid", "orientation",
"device-pixel-ratio", "min-device-pixel-ratio", "max-device-pixel-ratio",
"pointer", "any-pointer", "hover", "any-hover", "prefers-color-scheme",
"dynamic-range", "video-dynamic-range"
], mediaFeatures = keySet(mediaFeatures_);
var mediaValueKeywords_ = [
"landscape", "portrait", "none", "coarse", "fine", "on-demand", "hover",
"interlace", "progressive",
"dark", "light",
"standard", "high"
], mediaValueKeywords = keySet(mediaValueKeywords_);
var propertyKeywords_ = [
"align-content", "align-items", "align-self", "alignment-adjust",
"alignment-baseline", "all", "anchor-point", "animation", "animation-delay",
"animation-direction", "animation-duration", "animation-fill-mode",
"animation-iteration-count", "animation-name", "animation-play-state",
"animation-timing-function", "appearance", "azimuth", "backdrop-filter",
"backface-visibility", "background", "background-attachment",
"background-blend-mode", "background-clip", "background-color",
"background-image", "background-origin", "background-position",
"background-position-x", "background-position-y", "background-repeat",
"background-size", "baseline-shift", "binding", "bleed", "block-size",
"bookmark-label", "bookmark-level", "bookmark-state", "bookmark-target",
"border", "border-bottom", "border-bottom-color", "border-bottom-left-radius",
"border-bottom-right-radius", "border-bottom-style", "border-bottom-width",
"border-collapse", "border-color", "border-image", "border-image-outset",
"border-image-repeat", "border-image-slice", "border-image-source",
"border-image-width", "border-left", "border-left-color", "border-left-style",
"border-left-width", "border-radius", "border-right", "border-right-color",
"border-right-style", "border-right-width", "border-spacing", "border-style",
"border-top", "border-top-color", "border-top-left-radius",
"border-top-right-radius", "border-top-style", "border-top-width",
"border-width", "bottom", "box-decoration-break", "box-shadow", "box-sizing",
"break-after", "break-before", "break-inside", "caption-side", "caret-color",
"clear", "clip", "color", "color-profile", "column-count", "column-fill",
"column-gap", "column-rule", "column-rule-color", "column-rule-style",
"column-rule-width", "column-span", "column-width", "columns", "contain",
"content", "counter-increment", "counter-reset", "crop", "cue", "cue-after",
"cue-before", "cursor", "direction", "display", "dominant-baseline",
"drop-initial-after-adjust", "drop-initial-after-align",
"drop-initial-before-adjust", "drop-initial-before-align", "drop-initial-size",
"drop-initial-value", "elevation", "empty-cells", "fit", "fit-content", "fit-position",
"flex", "flex-basis", "flex-direction", "flex-flow", "flex-grow",
"flex-shrink", "flex-wrap", "float", "float-offset", "flow-from", "flow-into",
"font", "font-family", "font-feature-settings", "font-kerning",
"font-language-override", "font-optical-sizing", "font-size",
"font-size-adjust", "font-stretch", "font-style", "font-synthesis",
"font-variant", "font-variant-alternates", "font-variant-caps",
"font-variant-east-asian", "font-variant-ligatures", "font-variant-numeric",
"font-variant-position", "font-variation-settings", "font-weight", "gap",
"grid", "grid-area", "grid-auto-columns", "grid-auto-flow", "grid-auto-rows",
"grid-column", "grid-column-end", "grid-column-gap", "grid-column-start",
"grid-gap", "grid-row", "grid-row-end", "grid-row-gap", "grid-row-start",
"grid-template", "grid-template-areas", "grid-template-columns",
"grid-template-rows", "hanging-punctuation", "height", "hyphens", "icon",
"image-orientation", "image-rendering", "image-resolution", "inline-box-align",
"inset", "inset-block", "inset-block-end", "inset-block-start", "inset-inline",
"inset-inline-end", "inset-inline-start", "isolation", "justify-content",
"justify-items", "justify-self", "left", "letter-spacing", "line-break",
"line-height", "line-height-step", "line-stacking", "line-stacking-ruby",
"line-stacking-shift", "line-stacking-strategy", "list-style",
"list-style-image", "list-style-position", "list-style-type", "margin",
"margin-bottom", "margin-left", "margin-right", "margin-top", "marks",
"marquee-direction", "marquee-loop", "marquee-play-count", "marquee-speed",
"marquee-style", "mask-clip", "mask-composite", "mask-image", "mask-mode",
"mask-origin", "mask-position", "mask-repeat", "mask-size","mask-type",
"max-block-size", "max-height", "max-inline-size",
"max-width", "min-block-size", "min-height", "min-inline-size", "min-width",
"mix-blend-mode", "move-to", "nav-down", "nav-index", "nav-left", "nav-right",
"nav-up", "object-fit", "object-position", "offset", "offset-anchor",
"offset-distance", "offset-path", "offset-position", "offset-rotate",
"opacity", "order", "orphans", "outline", "outline-color", "outline-offset",
"outline-style", "outline-width", "overflow", "overflow-style",
"overflow-wrap", "overflow-x", "overflow-y", "padding", "padding-bottom",
"padding-left", "padding-right", "padding-top", "page", "page-break-after",
"page-break-before", "page-break-inside", "page-policy", "pause",
"pause-after", "pause-before", "perspective", "perspective-origin", "pitch",
"pitch-range", "place-content", "place-items", "place-self", "play-during",
"position", "presentation-level", "punctuation-trim", "quotes",
"region-break-after", "region-break-before", "region-break-inside",
"region-fragment", "rendering-intent", "resize", "rest", "rest-after",
"rest-before", "richness", "right", "rotate", "rotation", "rotation-point",
"row-gap", "ruby-align", "ruby-overhang", "ruby-position", "ruby-span",
"scale", "scroll-behavior", "scroll-margin", "scroll-margin-block",
"scroll-margin-block-end", "scroll-margin-block-start", "scroll-margin-bottom",
"scroll-margin-inline", "scroll-margin-inline-end",
"scroll-margin-inline-start", "scroll-margin-left", "scroll-margin-right",
"scroll-margin-top", "scroll-padding", "scroll-padding-block",
"scroll-padding-block-end", "scroll-padding-block-start",
"scroll-padding-bottom", "scroll-padding-inline", "scroll-padding-inline-end",
"scroll-padding-inline-start", "scroll-padding-left", "scroll-padding-right",
"scroll-padding-top", "scroll-snap-align", "scroll-snap-type",
"shape-image-threshold", "shape-inside", "shape-margin", "shape-outside",
"size", "speak", "speak-as", "speak-header", "speak-numeral",
"speak-punctuation", "speech-rate", "stress", "string-set", "tab-size",
"table-layout", "target", "target-name", "target-new", "target-position",
"text-align", "text-align-last", "text-combine-upright", "text-decoration",
"text-decoration-color", "text-decoration-line", "text-decoration-skip",
"text-decoration-skip-ink", "text-decoration-style", "text-emphasis",
"text-emphasis-color", "text-emphasis-position", "text-emphasis-style",
"text-height", "text-indent", "text-justify", "text-orientation",
"text-outline", "text-overflow", "text-rendering", "text-shadow",
"text-size-adjust", "text-space-collapse", "text-transform",
"text-underline-position", "text-wrap", "top", "touch-action", "transform", "transform-origin",
"transform-style", "transition", "transition-delay", "transition-duration",
"transition-property", "transition-timing-function", "translate",
"unicode-bidi", "user-select", "vertical-align", "visibility", "voice-balance",
"voice-duration", "voice-family", "voice-pitch", "voice-range", "voice-rate",
"voice-stress", "voice-volume", "volume", "white-space", "widows", "width",
"will-change", "word-break", "word-spacing", "word-wrap", "writing-mode", "z-index",
// SVG-specific
"clip-path", "clip-rule", "mask", "enable-background", "filter", "flood-color",
"flood-opacity", "lighting-color", "stop-color", "stop-opacity", "pointer-events",
"color-interpolation", "color-interpolation-filters",
"color-rendering", "fill", "fill-opacity", "fill-rule", "image-rendering",
"marker", "marker-end", "marker-mid", "marker-start", "paint-order", "shape-rendering", "stroke",
"stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin",
"stroke-miterlimit", "stroke-opacity", "stroke-width", "text-rendering",
"baseline-shift", "dominant-baseline", "glyph-orientation-horizontal",
"glyph-orientation-vertical", "text-anchor", "writing-mode",
], propertyKeywords = keySet(propertyKeywords_);
var nonStandardPropertyKeywords_ = [
"accent-color", "aspect-ratio", "border-block", "border-block-color", "border-block-end",
"border-block-end-color", "border-block-end-style", "border-block-end-width",
"border-block-start", "border-block-start-color", "border-block-start-style",
"border-block-start-width", "border-block-style", "border-block-width",
"border-inline", "border-inline-color", "border-inline-end",
"border-inline-end-color", "border-inline-end-style",
"border-inline-end-width", "border-inline-start", "border-inline-start-color",
"border-inline-start-style", "border-inline-start-width",
"border-inline-style", "border-inline-width", "content-visibility", "margin-block",
"margin-block-end", "margin-block-start", "margin-inline", "margin-inline-end",
"margin-inline-start", "overflow-anchor", "overscroll-behavior", "padding-block", "padding-block-end",
"padding-block-start", "padding-inline", "padding-inline-end",
"padding-inline-start", "scroll-snap-stop", "scrollbar-3d-light-color",
"scrollbar-arrow-color", "scrollbar-base-color", "scrollbar-dark-shadow-color",
"scrollbar-face-color", "scrollbar-highlight-color", "scrollbar-shadow-color",
"scrollbar-track-color", "searchfield-cancel-button", "searchfield-decoration",
"searchfield-results-button", "searchfield-results-decoration", "shape-inside", "zoom"
], nonStandardPropertyKeywords = keySet(nonStandardPropertyKeywords_);
var fontProperties_ = [
"font-display", "font-family", "src", "unicode-range", "font-variant",
"font-feature-settings", "font-stretch", "font-weight", "font-style"
], fontProperties = keySet(fontProperties_);
var counterDescriptors_ = [
"additive-symbols", "fallback", "negative", "pad", "prefix", "range",
"speak-as", "suffix", "symbols", "system"
], counterDescriptors = keySet(counterDescriptors_);
var colorKeywords_ = [
"aliceblue", "antiquewhite", "aqua", "aquamarine", "azure", "beige",
"bisque", "black", "blanchedalmond", "blue", "blueviolet", "brown",
"burlywood", "cadetblue", "chartreuse", "chocolate", "coral", "cornflowerblue",
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan", "darkgoldenrod",
"darkgray", "darkgreen", "darkgrey", "darkkhaki", "darkmagenta", "darkolivegreen",
"darkorange", "darkorchid", "darkred", "darksalmon", "darkseagreen",
"darkslateblue", "darkslategray", "darkslategrey", "darkturquoise", "darkviolet",
"deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro", "ghostwhite",
"gold", "goldenrod", "gray", "grey", "green", "greenyellow", "honeydew",
"hotpink", "indianred", "indigo", "ivory", "khaki", "lavender",
"lavenderblush", "lawngreen", "lemonchiffon", "lightblue", "lightcoral",
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey", "lightpink",
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey",
"lightsteelblue", "lightyellow", "lime", "limegreen", "linen", "magenta",
"maroon", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple",
"mediumseagreen", "mediumslateblue", "mediumspringgreen", "mediumturquoise",
"mediumvioletred", "midnightblue", "mintcream", "mistyrose", "moccasin",
"navajowhite", "navy", "oldlace", "olive", "olivedrab", "orange", "orangered",
"orchid", "palegoldenrod", "palegreen", "paleturquoise", "palevioletred",
"papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue",
"purple", "rebeccapurple", "red", "rosybrown", "royalblue", "saddlebrown",
"salmon", "sandybrown", "seagreen", "seashell", "sienna", "silver", "skyblue",
"slateblue", "slategray", "slategrey", "snow", "springgreen", "steelblue", "tan",
"teal", "thistle", "tomato", "turquoise", "violet", "wheat", "white",
"whitesmoke", "yellow", "yellowgreen"
], colorKeywords = keySet(colorKeywords_);
var valueKeywords_ = [
"above", "absolute", "activeborder", "additive", "activecaption", "afar",
"after-white-space", "ahead", "alias", "all", "all-scroll", "alphabetic", "alternate",
"always", "amharic", "amharic-abegede", "antialiased", "appworkspace",
"arabic-indic", "armenian", "asterisks", "attr", "auto", "auto-flow", "avoid", "avoid-column", "avoid-page",
"avoid-region", "axis-pan", "background", "backwards", "baseline", "below", "bidi-override", "binary",
"bengali", "blink", "block", "block-axis", "blur", "bold", "bolder", "border", "border-box",
"both", "bottom", "break", "break-all", "break-word", "brightness", "bullets", "button",
"buttonface", "buttonhighlight", "buttonshadow", "buttontext", "calc", "cambodian",
"capitalize", "caps-lock-indicator", "caption", "captiontext", "caret",
"cell", "center", "checkbox", "circle", "cjk-decimal", "cjk-earthly-branch",
"cjk-heavenly-stem", "cjk-ideographic", "clear", "clip", "close-quote",
"col-resize", "collapse", "color", "color-burn", "color-dodge", "column", "column-reverse",
"compact", "condensed", "conic-gradient", "contain", "content", "contents",
"content-box", "context-menu", "continuous", "contrast", "copy", "counter", "counters", "cover", "crop",
"cross", "crosshair", "cubic-bezier", "currentcolor", "cursive", "cyclic", "darken", "dashed", "decimal",
"decimal-leading-zero", "default", "default-button", "dense", "destination-atop",
"destination-in", "destination-out", "destination-over", "devanagari", "difference",
"disc", "discard", "disclosure-closed", "disclosure-open", "document",
"dot-dash", "dot-dot-dash",
"dotted", "double", "down", "drop-shadow", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out",
"element", "ellipse", "ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede",
"ethiopic-abegede-am-et", "ethiopic-abegede-gez", "ethiopic-abegede-ti-er",
"ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er",
"ethiopic-halehame-aa-et", "ethiopic-halehame-am-et",
"ethiopic-halehame-gez", "ethiopic-halehame-om-et",
"ethiopic-halehame-sid-et", "ethiopic-halehame-so-et",
"ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig",
"ethiopic-numeric", "ew-resize", "exclusion", "expanded", "extends", "extra-condensed",
"extra-expanded", "fantasy", "fast", "fill", "fill-box", "fixed", "flat", "flex", "flex-end", "flex-start", "footnotes",
"forwards", "from", "geometricPrecision", "georgian", "grayscale", "graytext", "grid", "groove",
"gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hard-light", "hebrew",
"help", "hidden", "hide", "higher", "highlight", "highlighttext",
"hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "hue", "hue-rotate", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite",
"infobackground", "infotext", "inherit", "initial", "inline", "inline-axis",
"inline-block", "inline-flex", "inline-grid", "inline-table", "inset", "inside", "intrinsic", "invert",
"italic", "japanese-formal", "japanese-informal", "justify", "kannada",
"katakana", "katakana-iroha", "keep-all", "khmer",
"korean-hangul-formal", "korean-hanja-formal", "korean-hanja-informal",
"landscape", "lao", "large", "larger", "left", "level", "lighter", "lighten",
"line-through", "linear", "linear-gradient", "lines", "list-item", "listbox", "listitem",
"local", "logical", "loud", "lower", "lower-alpha", "lower-armenian",
"lower-greek", "lower-hexadecimal", "lower-latin", "lower-norwegian",
"lower-roman", "lowercase", "ltr", "luminosity", "malayalam", "manipulation", "match", "matrix", "matrix3d",
"media-play-button", "media-slider", "media-sliderthumb",
"media-volume-slider", "media-volume-sliderthumb", "medium",
"menu", "menulist", "menulist-button",
"menutext", "message-box", "middle", "min-intrinsic",
"mix", "mongolian", "monospace", "move", "multiple", "multiple_mask_images", "multiply", "myanmar", "n-resize",
"narrower", "ne-resize", "nesw-resize", "no-close-quote", "no-drop",
"no-open-quote", "no-repeat", "none", "normal", "not-allowed", "nowrap",
"ns-resize", "numbers", "numeric", "nw-resize", "nwse-resize", "oblique", "octal", "opacity", "open-quote",
"optimizeLegibility", "optimizeSpeed", "oriya", "oromo", "outset",
"outside", "outside-shape", "overlay", "overline", "padding", "padding-box",
"painted", "page", "paused", "persian", "perspective", "pinch-zoom", "plus-darker", "plus-lighter",
"pointer", "polygon", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d",
"progress", "push-button", "radial-gradient", "radio", "read-only",
"read-write", "read-write-plaintext-only", "rectangle", "region",
"relative", "repeat", "repeating-linear-gradient", "repeating-radial-gradient",
"repeating-conic-gradient", "repeat-x", "repeat-y", "reset", "reverse",
"rgb", "rgba", "ridge", "right", "rotate", "rotate3d", "rotateX", "rotateY",
"rotateZ", "round", "row", "row-resize", "row-reverse", "rtl", "run-in", "running",
"s-resize", "sans-serif", "saturate", "saturation", "scale", "scale3d", "scaleX", "scaleY", "scaleZ", "screen",
"scroll", "scrollbar", "scroll-position", "se-resize", "searchfield",
"searchfield-cancel-button", "searchfield-decoration",
"searchfield-results-button", "searchfield-results-decoration", "self-start", "self-end",
"semi-condensed", "semi-expanded", "separate", "sepia", "serif", "show", "sidama",
"simp-chinese-formal", "simp-chinese-informal", "single",
"skew", "skewX", "skewY", "skip-white-space", "slide", "slider-horizontal",
"slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "soft-light", "solid", "somali",
"source-atop", "source-in", "source-out", "source-over", "space", "space-around", "space-between", "space-evenly", "spell-out", "square",
"square-button", "start", "static", "status-bar", "stretch", "stroke", "stroke-box", "sub",
"subpixel-antialiased", "svg_masks", "super", "sw-resize", "symbolic", "symbols", "system-ui", "table",
"table-caption", "table-cell", "table-column", "table-column-group",
"table-footer-group", "table-header-group", "table-row", "table-row-group",
"tamil",
"telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai",
"thick", "thin", "threeddarkshadow", "threedface", "threedhighlight",
"threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er",
"tigrinya-er-abegede", "tigrinya-et", "tigrinya-et-abegede", "to", "top",
"trad-chinese-formal", "trad-chinese-informal", "transform",
"translate", "translate3d", "translateX", "translateY", "translateZ",
"transparent", "ultra-condensed", "ultra-expanded", "underline", "unidirectional-pan", "unset", "up",
"upper-alpha", "upper-armenian", "upper-greek", "upper-hexadecimal",
"upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url",
"var", "vertical", "vertical-text", "view-box", "visible", "visibleFill", "visiblePainted",
"visibleStroke", "visual", "w-resize", "wait", "wave", "wider",
"window", "windowframe", "windowtext", "words", "wrap", "wrap-reverse", "x-large", "x-small", "xor",
"xx-large", "xx-small"
], valueKeywords = keySet(valueKeywords_);
var allWords = documentTypes_.concat(mediaTypes_).concat(mediaFeatures_).concat(mediaValueKeywords_)
.concat(propertyKeywords_).concat(nonStandardPropertyKeywords_).concat(colorKeywords_)
.concat(valueKeywords_);
CodeMirror.registerHelper("hintWords", "css", allWords);
function tokenCComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
if (maybeEnd && ch == "/") {
state.tokenize = null;
break;
}
maybeEnd = (ch == "*");
}
return ["comment", "comment"];
}
CodeMirror.defineMIME("text/css", {
documentTypes: documentTypes,
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
mediaValueKeywords: mediaValueKeywords,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
fontProperties: fontProperties,
counterDescriptors: counterDescriptors,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
tokenHooks: {
"/": function(stream, state) {
if (!stream.eat("*")) return false;
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
}
},
name: "css"
});
CodeMirror.defineMIME("text/x-scss", {
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
mediaValueKeywords: mediaValueKeywords,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
fontProperties: fontProperties,
allowNested: true,
lineComment: "//",
tokenHooks: {
"/": function(stream, state) {
if (stream.eat("/")) {
stream.skipToEnd();
return ["comment", "comment"];
} else if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
} else {
return ["operator", "operator"];
}
},
":": function(stream) {
if (stream.match(/^\s*\{/, false))
return [null, null]
return false;
},
"$": function(stream) {
stream.match(/^[\w-]+/);
if (stream.match(/^\s*:/, false))
return ["variable-2", "variable-definition"];
return ["variable-2", "variable"];
},
"#": function(stream) {
if (!stream.eat("{")) return false;
return [null, "interpolation"];
}
},
name: "css",
helperType: "scss"
});
CodeMirror.defineMIME("text/x-less", {
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
mediaValueKeywords: mediaValueKeywords,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
fontProperties: fontProperties,
allowNested: true,
lineComment: "//",
tokenHooks: {
"/": function(stream, state) {
if (stream.eat("/")) {
stream.skipToEnd();
return ["comment", "comment"];
} else if (stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
} else {
return ["operator", "operator"];
}
},
"@": function(stream) {
if (stream.eat("{")) return [null, "interpolation"];
if (stream.match(/^(charset|document|font-face|import|(-(moz|ms|o|webkit)-)?keyframes|media|namespace|page|supports)\b/i, false)) return false;
stream.eatWhile(/[\w\\\-]/);
if (stream.match(/^\s*:/, false))
return ["variable-2", "variable-definition"];
return ["variable-2", "variable"];
},
"&": function() {
return ["atom", "atom"];
}
},
name: "css",
helperType: "less"
});
CodeMirror.defineMIME("text/x-gss", {
documentTypes: documentTypes,
mediaTypes: mediaTypes,
mediaFeatures: mediaFeatures,
propertyKeywords: propertyKeywords,
nonStandardPropertyKeywords: nonStandardPropertyKeywords,
fontProperties: fontProperties,
counterDescriptors: counterDescriptors,
colorKeywords: colorKeywords,
valueKeywords: valueKeywords,
supportsAtComponent: true,
tokenHooks: {
"/": function(stream, state) {
if (!stream.eat("*")) return false;
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
}
},
name: "css",
helperType: "gss"
});
});

View File

@@ -0,0 +1,70 @@
// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: https://codemirror.net/5/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("../../lib/codemirror"), require("../../addon/mode/simple"), require("../../addon/mode/multiplex"));
else if (typeof define == "function" && define.amd) // AMD
define(["../../lib/codemirror", "../../addon/mode/simple", "../../addon/mode/multiplex"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.defineSimpleMode("handlebars-tags", {
start: [
{ regex: /\{\{\{/, push: "handlebars_raw", token: "tag" },
{ regex: /\{\{!--/, push: "dash_comment", token: "comment" },
{ regex: /\{\{!/, push: "comment", token: "comment" },
{ regex: /\{\{/, push: "handlebars", token: "tag" }
],
handlebars_raw: [
{ regex: /\}\}\}/, pop: true, token: "tag" },
],
handlebars: [
{ regex: /\}\}/, pop: true, token: "tag" },
// Double and single quotes
{ regex: /"(?:[^\\"]|\\.)*"?/, token: "string" },
{ regex: /'(?:[^\\']|\\.)*'?/, token: "string" },
// Handlebars keywords
{ regex: />|[#\/]([A-Za-z_]\w*)/, token: "keyword" },
{ regex: /(?:else|this)\b/, token: "keyword" },
// Numeral
{ regex: /\d+/i, token: "number" },
// Atoms like = and .
{ regex: /=|~|@|true|false/, token: "atom" },
// Paths
{ regex: /(?:\.\.\/)*(?:[A-Za-z_][\w\.]*)+/, token: "variable-2" }
],
dash_comment: [
{ regex: /--\}\}/, pop: true, token: "comment" },
// Commented code
{ regex: /./, token: "comment"}
],
comment: [
{ regex: /\}\}/, pop: true, token: "comment" },
{ regex: /./, token: "comment" }
],
meta: {
blockCommentStart: "{{--",
blockCommentEnd: "--}}"
}
});
CodeMirror.defineMode("handlebars", function(config, parserConfig) {
var handlebars = CodeMirror.getMode(config, "handlebars-tags");
if (!parserConfig || !parserConfig.base) return handlebars;
return CodeMirror.multiplexingMode(
CodeMirror.getMode(config, parserConfig.base),
{open: "{{", close: /\}\}\}?/, mode: handlebars, parseDelimiters: true}
);
});
CodeMirror.defineMIME("text/x-handlebars-template", "handlebars");
});

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