Initial Commit

This commit is contained in:
Docker VM 2024-07-06 18:27:29 -04:00
commit b2900017d2
12 changed files with 283 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/vendor/

17
composer.json Normal file
View File

@ -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": {}
}

View File

@ -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()
{
//
}
}

38
src/composer.json Normal file
View File

@ -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
}

View File

@ -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;
}

86
src/resources/js/cards.js Normal file
View File

@ -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)}`);
}
}

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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>

14
src/vite.config.js Normal file
View File

@ -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,
}),
],
});

13
tailwind.config.js Normal file
View File

@ -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'),
],
};