Initial Commit
This commit is contained in:
commit
b2900017d2
|
@ -0,0 +1 @@
|
||||||
|
/vendor/
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "dylanbanta/responsive-cards",
|
||||||
|
"description": "A Laravel component that responsively displays up to 3 cards in a row. The cards size is determined by character count.",
|
||||||
|
"type": "larave-component",
|
||||||
|
"license": "MIT",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Dylanbanta\\ResponsiveCards\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Dylan Banta"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Dylanbanta\ResponsiveCards;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
class ResponsiveCardsServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
// Load views
|
||||||
|
$this->loadViewsFrom(__DIR__ . '/resources/views', 'responsive-cards');
|
||||||
|
|
||||||
|
// Publish assets
|
||||||
|
$this->publishes([
|
||||||
|
__DIR__ . '/resources/css/cards.css' => public_path('vendor/responsive-cards/css/cards.css'),
|
||||||
|
__DIR__ . '/resources/js/cards.js' => public_path('vendor/responsive-cards/js/cards.js'),
|
||||||
|
], 'public');
|
||||||
|
|
||||||
|
// Publish views
|
||||||
|
$this->publishes([
|
||||||
|
__DIR__ . '/resources/views' => resource_path('views/vendor/responsive-cards'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"name": "dylanbanta/responsive-cards",
|
||||||
|
"description": "A Laravel package for custom responsive cards",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Dylanbanta\\ResponsiveCards\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Dylanbanta\\ResponsiveCards\\ResponsiveCardsServiceProvider"
|
||||||
|
],
|
||||||
|
"aliases": {
|
||||||
|
"ResponsiveCards": "Dylanbanta\\ResponsiveCards\\Facades\\ResponsiveCards"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.3|^8.0",
|
||||||
|
"illuminate/support": "^8.0|^9.0",
|
||||||
|
"tailwindcss/tailwindcss": "^2.0",
|
||||||
|
"tailwindcss/typography": "^0.4.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"post-autoload-dump": [
|
||||||
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
|
"@php artisan package:discover --ansi"
|
||||||
|
],
|
||||||
|
"post-update-cmd": [
|
||||||
|
"@php artisan vendor:publish --tag=responsive-cards-config --ansi"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"prefer-stable": true
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
.my-card {
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
transition: transform 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-card h2 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-card p {
|
||||||
|
color: #666;
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
console.log("DOM fully loaded and parsed.");
|
||||||
|
adjustCardWidths();
|
||||||
|
});
|
||||||
|
|
||||||
|
function adjustCardWidths() {
|
||||||
|
const container = document.getElementById('cards-container');
|
||||||
|
if (!container) {
|
||||||
|
console.error('cards-container not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log("cards-container found:", container);
|
||||||
|
|
||||||
|
const cards = Array.from(container.querySelectorAll('.adjust-card'));
|
||||||
|
console.log("Found cards:", cards);
|
||||||
|
|
||||||
|
let currentRowCards = [];
|
||||||
|
let currentRowWidth = 0;
|
||||||
|
const rowMaxWidth = 3; // Assuming a row can hold up to 3 'col-span-1' cards
|
||||||
|
|
||||||
|
cards.forEach((card, index) => {
|
||||||
|
const textLength = card.textContent.length;
|
||||||
|
console.log("Card text length:", textLength);
|
||||||
|
|
||||||
|
let colSpan = 1; // Default to smallest size
|
||||||
|
if (textLength > 300) {
|
||||||
|
colSpan = 3;
|
||||||
|
} else if (textLength > 150) {
|
||||||
|
colSpan = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Assigning colSpan:", colSpan + " for card:", card);
|
||||||
|
|
||||||
|
// Remove existing col-span classes
|
||||||
|
card.classList.remove('lg:col-span-1', 'lg:col-span-2', 'lg:col-span-3');
|
||||||
|
// Add the new col-span class
|
||||||
|
card.classList.add(`lg:col-span-${colSpan}`);
|
||||||
|
|
||||||
|
// Check if adding this card would exceed the row max width
|
||||||
|
if (currentRowWidth + colSpan > rowMaxWidth) {
|
||||||
|
adjustRow(currentRowCards, currentRowWidth, rowMaxWidth);
|
||||||
|
currentRowWidth = colSpan;
|
||||||
|
currentRowCards = [card];
|
||||||
|
} else {
|
||||||
|
currentRowWidth += colSpan;
|
||||||
|
currentRowCards.push(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust the last row if it's the last card
|
||||||
|
if (index === cards.length - 1) {
|
||||||
|
adjustRow(currentRowCards, currentRowWidth, rowMaxWidth);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function adjustRow(rowCards, currentRowWidth, rowMaxWidth) {
|
||||||
|
if (rowCards.length === 1) {
|
||||||
|
// Single card in the row
|
||||||
|
const card = rowCards[0];
|
||||||
|
card.classList.remove('lg:col-span-1', 'lg:col-span-2', 'lg:col-span-3');
|
||||||
|
card.classList.add(`lg:col-span-${rowMaxWidth}`);
|
||||||
|
} else if (rowCards.length === 2) {
|
||||||
|
// Two cards in the row
|
||||||
|
const firstCard = rowCards[0];
|
||||||
|
const secondCard = rowCards[1];
|
||||||
|
const firstColSpan = firstCard.classList.contains('lg:col-span-2') ? 2 : 1;
|
||||||
|
const secondColSpan = secondCard.classList.contains('lg:col-span-2') ? 2 : 1;
|
||||||
|
if (currentRowWidth > rowMaxWidth) {
|
||||||
|
// Push second card to the next row and expand the first card
|
||||||
|
secondCard.classList.remove(`lg:col-span-${secondColSpan}`);
|
||||||
|
secondCard.classList.add('lg:col-span-1'); // reset to span 1 for next row processing
|
||||||
|
firstCard.classList.remove(`lg:col-span-${firstColSpan}`);
|
||||||
|
firstCard.classList.add(`lg:col-span-${rowMaxWidth}`);
|
||||||
|
} else {
|
||||||
|
// Expand the second card to fill the row
|
||||||
|
secondCard.classList.remove(`lg:col-span-${secondColSpan}`);
|
||||||
|
secondCard.classList.add(`lg:col-span-${rowMaxWidth - firstColSpan}`);
|
||||||
|
}
|
||||||
|
} else if (rowCards.length === 3) {
|
||||||
|
// Three cards in the row, expand the last card to fill the row
|
||||||
|
const lastCard = rowCards[2];
|
||||||
|
const lastColSpan = lastCard.classList.contains('lg:col-span-2') ? 2 : 1;
|
||||||
|
lastCard.classList.remove(`lg:col-span-${lastColSpan}`);
|
||||||
|
lastCard.classList.add(`lg:col-span-${rowMaxWidth - (currentRowWidth - lastColSpan)}`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<div id="{{ $entry['title'] }}" class="p-6 bg-gray-700 rounded-lg shadow-md flex flex-col adjust-card highlight-card">
|
||||||
|
<h3 class="text-xl font-medium mt-4 text-center">{{ $entry['title'] }}</h3>
|
||||||
|
<p class="mt-2">{{ $entry['message'] }}</p>
|
||||||
|
</div>
|
|
@ -0,0 +1,25 @@
|
||||||
|
@extends('layouts.card-layout')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
@php
|
||||||
|
$data = [
|
||||||
|
['title' => 'Card 1', 'message' => str_repeat('Short content. ', 1)],
|
||||||
|
['title' => 'Card 2', 'message' => str_repeat('Short content. ', 1)],
|
||||||
|
['title' => 'Card 3', 'message' => str_repeat('Short content. ', 1)],
|
||||||
|
['title' => 'Card 4', 'message' => str_repeat('Short content. ', 1)],
|
||||||
|
['title' => 'Card 5', 'message' => str_repeat('Medium content. ', 10)],
|
||||||
|
['title' => 'Card 6', 'message' => str_repeat('Medium content. ', 10)],
|
||||||
|
['title' => 'Card 7', 'message' => str_repeat('Short content. ', 1)],
|
||||||
|
['title' => 'Card 8', 'message' => str_repeat('Short content. (Forced long) ', 1)],
|
||||||
|
['title' => 'Card 9', 'message' => str_repeat('Long content. ', 25)],
|
||||||
|
['title' => 'Card 10', 'message' => str_repeat('Short content. ', 1)],
|
||||||
|
['title' => 'Card 11', 'message' => str_repeat('Short content. (Forced medium) ', 1)],
|
||||||
|
['title' => 'Card 12', 'message' => str_repeat('Long content. ', 25)],
|
||||||
|
['title' => 'Card 13', 'message' => str_repeat('Medium content. (Forced long) ', 10)],
|
||||||
|
['title' => 'Card 14', 'message' => str_repeat('Medium content. (Forced long) ', 10)],
|
||||||
|
];
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<x-cards :cardsData="$data" cardTemplate="card-templates.default" />
|
||||||
|
@endsection
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
@props(['cardsData', 'cardTemplate'])
|
||||||
|
|
||||||
|
<section class="bg-gray-900 text-gray-100 p-10">
|
||||||
|
<div class="max-w-7xl mx-auto">
|
||||||
|
<h2 class="text-center text-2xl font-semibold"></h2>
|
||||||
|
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6 mt-6" id="cards-container">
|
||||||
|
@foreach ($cardsData as $entry)
|
||||||
|
@include($cardTemplate, ['entry' => $entry])
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>@yield('title', 'Card Test')</title>
|
||||||
|
@vite(['resources/css/app.css', 'resources/css/cards.css', 'resources/js/cards.js'])
|
||||||
|
@livewireStyles
|
||||||
|
<!-- Font Awesome -->
|
||||||
|
<script src="https://kit.fontawesome.com/da6de140e9.js" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<!--Bootstrap-->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="bg-gray-800 text-white dark:bg-gray-900 dark:text-gray-300">
|
||||||
|
<main>
|
||||||
|
@yield('content')
|
||||||
|
</main>
|
||||||
|
@livewireScripts
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import laravel from 'laravel-vite-plugin';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
laravel({
|
||||||
|
input: [
|
||||||
|
'vendor/dylanbanta/responsive-cards/src/resources/css/cards.css',
|
||||||
|
'vendor/dylanbanta/responsive-cards/src/resources/js/cards.js'
|
||||||
|
],
|
||||||
|
refresh: true,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
module.exports = {
|
||||||
|
content: [
|
||||||
|
'./vendor/dylanbanta/responsive-cards/src/resources/views/**/*.blade.php',
|
||||||
|
'./vendor/dylanbanta/responsive-cards/src/resources/js/**/*.js',
|
||||||
|
'./vendor/dylanbanta/responsive-cards/src/resources/css/**/*.css',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {},
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
require('@tailwindcss/typography'),
|
||||||
|
],
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user