/* 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;
}
                                 
                                 
                        <!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>
                                 
                                 
                        <?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);
	}
                                 
                                 
                        <!--
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>
                                 
                                 
                        <!--
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>
                                 
                                 
                        // 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>