/ Gists

Gists

On gists

Css grid by KevinPowell sheats

CSS CSS trick

grid.css #

/* Adjustable grid */
.grid {
 --column-count: 3;
 display: grid;
 grid-template-columns: repeat(var(--column-count), 1fr);
}

/* modifiers */
.grid-3 { --column-count: 3; }
.grid-4 { --column-count: 4; }
.grid-5 { --column-count: 5; }

/* custom */
.grid { --column-count: 1; }
@media (min-width: 600px) {
 .grid { --column-count: 3; }
}
@media (min-width: 960px) {
 .grid { --column-count: 4; }
}

/*
-----------------------------------------------------
*/

/* grid auto-columns */
.auto-grid {
 display: grid;
 grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
}

/*
-----------------------------------------------------
*/

/* Pushing the footer down */
.main-layout {
 min-height: 100vh;
 display: grid;
 grid-template-rows: rows 1fr rows;
}


/*
-----------------------------------------------------
*/

/* The stack */
.the-stack {
 display: grid;
 grid-template-areas: "stack";
 place-items: center; 
}
.the-stack > * {
 grid-area: stack;
}

On gists

BroadCastChannel (sync between 2 tabs immediately)

JavaScript

index.html #

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <body>
        <button>CLICK ME</button>

        <script>
            const channel = new BroadcastChannel('myChannel');
            document.getElementsByTagName('button')[0].addEventListener('click', e => {
                channel.postMessage('Hello from Tab 1' + new Date().getSeconds);

                console.log('CHANNEL 1');
            });

            channel.onmessage = event => {
                console.log('Message received in Tab 2:', event.data);

                console.log('CHANNEL 2');
            };
        </script>
    </body>
</html>

On gists

Delete recursively from child to parent

PHP AW

delete-recursively-from-child.ph #

<?php

	private function deleteDuplicateRecursive(Tables\Navigation $duplicateItem)
	{
		/*
		// OLD
		$findDescendants = function(Tables\Navigation $parent, array $stack = [], $level = 1) use (&$findDescendants) {
			$children = $this->navigation->getAdjacencyList($parent->domain_id)->getChildren($parent->id);
			
			foreach ($children as $child) {
				$stack[$level][] = $child;
				$stack = $findDescendants($child, $stack, $level + 1);
			} 
				
			return $stack;
		};

		// mazeme deti odspoda nahoru
		$descendants = $findDescendants($duplicateItem);

		foreach (array_reverse($descendants, true) as $level => $descendantArr) {
			foreach ($descendantArr as $descendant) {
				$this->deleteDuplicate($descendant);
			}
		}
		*/

    // NEW, better, shorter
		$children = $this->navigation->getAdjacencyList($duplicateItem->domain_id)->getChildren($duplicateItem->id);
		foreach ($children as $child) {
			$this->deleteDuplicateRecursive($child);
		}

		// na zaver i roota
		$this->deleteDuplicate($duplicateItem);
	}

On gists

full width in container

CSS CSS trick

index.html #

<!--
https://jsbin.com/heqamezuju/edit?html,css,output
-->

	<grid>
		
		<item class="l">
			
			aaa
			
		</item>
		<item class="r">
			
			bbb
			
		</item>
	</grid>


  <style>
    grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	max-width: 500px;
	outline: 2px solid gray;
	height: 500px;
	margin: auto;
	
}


item {
	padding: 10px;
}

.r, .l {
	position: relative;	
	isolation: isolate;
}

.r:after {
	background: lightgray;
	top: 0;
	bottom: 0;
	left: 0;
	width: 50vw;
	position: absolute;
	content: "";
	z-index: -1;
}


.l:after {
	background: lightpink;
	top: 0;
	bottom: 0;
	right: 0;
	width: 50vw;
	position: absolute;
	content: "";
	z-index: -1;
}


    
  </style>



On gists

Advanced from Tailwind 3

Tailwind CSS

index.html #

<!--
https://lab.rjwebdesign.cz/tailwindcss/advanced/
-->

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <link href="./dist/output.css" rel="stylesheet" />
    </head>
    <body class="p-5">
        <h1 class="mb-4 font-bold text-3xl">1) Peer / Group</h1>
        <div class="peer group group/second group/third grid place-items-center bg-slate-600 w-20 h-20 mt-10">
            <div class="bg-black w-5 h-5 group-hover:bg-red-500"></div>
            <div class="bg-black w-5 h-5 group-hover/second:bg-green-500"></div>
            <div class="bg-black w-5 h-5 group-hover/third:bg-orange-500"></div>
        </div>
        <div class="w-20 h-20 bg-orange-400 mt-10 peer-hover:bg-violet-300"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">2) Animation / Transition</h1>
        <div class="w-20 h-20 bg-teal-700 transition-all hover:bg-red-300 delay-300 duration-150"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">3) Responsivenes / BP (ranges)</h1>
        <div class="w-20 h-20 bg-red-500 md:max-lg:bg-green-500"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">4) Dynamic variants / props / values</h1>
        <div class="w-20 h-20 bg-[theme('colors.blue.300')]"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">5) TW extend / config</h1>
        <div class="w-20 h-20 neon-blue"></div>

        <hr class="my-5" />
        <h1 class="mb-4 font-bold text-3xl">6) TW extend -> COLORS</h1>
        <div class="text-primary">Hello how are you?</div>
    </body>
</html>

On gists

Vue.js design pattern

JS Patterns Vue.js

pattern.js #

// https://blog.logrocket.com/exploring-advanced-design-patterns-vue-js/
// + MORE ... builder, adapter more usable ...

// BUILDER

// FormBuilder.js
class FormBuilder {
  constructor() {
    this.formFields = [];
  }
  addTextField(name, label, placeholder = '') {
    this.formFields.push({
      type: 'text',
      name,
      label,
      placeholder,
    });
    return this; // Return the builder instance for method chaining
  }
  addNumberField(...) {
    // Add a number field
  }
  addSelectField(...) {
    // Add a select field
  }
  build() {
    return this.formFields;
  }
}
export default FormBuilder;


//  Form.vue 
import FormBuilder from './helpers/FormBuilder';

export default {
  data() {
    return {
      formFields: [],
      formData: {}, // Add a data property to store the form data
    };
  },
  created() {
    /* 
     * Use the FormBuilder class and its methods 
     * to construct the `formFields` object array 
     * with different form fields.
     */
    this.formFields = new FormBuilder()
      .addTextField('name', 'Name')
      .addNumberField(...)
      .addSelectField(...)
      .build();
  },
  methods: {
    handleSubmit() {
      // Log the form data when the form is submitted
      console.log(this.formData);
    },
  },
};



// ADAPTER
// UserAdapter.js
class UserAdapter {
  constructor(externalUserData) {
    this.externalUserData = externalUserData;
  }
  adapt() {
    /*
     * Adapt the external user data to match
     * the component's expected format.
     *
     * Considering the structure of the expected
     * response, grab the right object array
     * (`results`) and its only value.
     *
     * @link https://randomuser.me/api/
     */
    const userData = this.externalUserData.results[0];
    return {
      name: `${userData.name.first} ${userData.name.last}`,
      email: userData.email,
      gender: userData.gender,
      location: `${userData.location.city}, ${userData.location.country}`,
      displayPic: userData.picture.large,
    };
  }
}
export default UserAdapter;

import UserAdapter from './UserAdapter';

export default {
  data() {
    return {
      userAdapter: null,
      user: null
    };
  },
  created() {
    /*
     * Get user data from an external API 
     * with a different format.
     */
    async created() {
      try {
        // Make an API call
        const response = await fetch('...');
        if (!response.ok) {
          throw new Error('Failed to fetch external user data');
        }
        const externalUserData = await response.json();

        /*
         * Create an adapter to convert external weather data 
         * to the format expected by the component.
         */
        this.userAdapter = new UserAdapter(externalUserData);

        // Adapt the data to the component's expected format
        this.user = this.userAdapter.adapt();
      } catch (error) {
        console.error('Error fetching external user data:', error);
        this.errorMessage = 'Failed to load user data. Please try again later.';
      }
    },
  }
};




// Composable pattern
// userPreferences.js
import { ref } from 'vue';

const theme = ref('light');
const language = ref('english');
const notifications = ref(true);

// Getter for theme
const getTheme = () => theme.value;

// Setter for theme
const setTheme = (newTheme) => {
  theme.value = newTheme;
};

// Getter for language
const getLanguage = () => language.value;

// Setter for language
const setLanguage = (newLanguage) => {
  language.value = newLanguage;
};

// Getter for notifications
const getNotificationsEnabled = () => notifications.value;

// Setter for notifications
const setNotificationsEnabled = (enabled) => {
  notifications.value = enabled;
};

export {
  getTheme,
  setTheme,
  getLanguage,
  setLanguage,
  getNotificationsEnabled,
  setNotificationsEnabled,
};


// themeSelector.js
import { computed } from 'vue';
import { getTheme, setTheme } from '../utils/userPreferences';

export function useThemeSelection() {
  const selectedTheme = computed({
    get: () => getTheme(),
    set: (newTheme) => setTheme(newTheme),
  });
  return {
    selectedTheme,
  };
}

// ThemeSelector.vue
<template>
  <div>
    <label for="theme-switch">Theme</label>
    <select id="theme-switch" @change="handleChange" v-model="selectedTheme">
      <option value="light">Light</option>
      <option value="dark">Dark</option>
    </select>
  </div>
</template>
<script>
import { defineComponent } from 'vue';
import { useThemeSelection } from '../composables/themeSelector';

export default defineComponent({
  setup() {
    const { selectedTheme } = useThemeSelection();
    const handleChange = (event) => {
      const newTheme = event.target.value;
      selectedTheme.value = newTheme; // Set the new theme
    };
    return {
      selectedTheme,
      handleChange,
    };
  },
});
</script>


// AnyOther.vue
<template>
  <div class="settings">
    <div class="settings-row">
      <ThemeSelector />
      <div :class="selectedTheme">
        Here's how the {{ selectedTheme }} theme looks like.
      </div>
    </div>
  </div>
</template>

<script>
import { defineComponent } from 'vue';
import { useThemeSelection } from './composables/themeSelector';
import ThemeSelector from './components/ThemeSelector';

export default defineComponent({
  setup() {
    const { selectedTheme } = useThemeSelection();

    return {
      selectedTheme,
    };
  },
  components: {
    ThemeSelector
  },
});
</script>

<style>
.light {
  background-color: #fff;
  color: #000;
}
.dark {
  background-color: #000;
  color: #fff;
}
</style>