# Pattern

## What is it

## When to use it

## How to use it

Uses absolute positioning. This is a testYou might need to add relative positioning to it's container.

If you wish to create a custom element, that extends another HTML element, the native element has to be extended in customElements.define(). Custom elements that inherit native elements are also known as "type extension custom elements".

another one

If you wish to create a custom element, that extends another HTML element, the native element has to be extended in customElements.define(). Custom elements that inherit native elements are also known as "type extension custom elements".

     @import url("https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap");
    sticky-note-wrapper {
    	-webkit-box-sizing: border-box;
    	        box-sizing: border-box;
    	border: 1px solid transparent;
    	border-radius: 50%;
    	display: inline-block;
    	height: 0.5rem;
    	position: relative;
    	width: 0.5rem;
    }
    sticky-note-wrapper * {
    	-webkit-box-sizing: border-box;
    	        box-sizing: border-box;
    }
    sticky-note-wrapper sticky-note {
    	cursor: -webkit-grab;
    	cursor: grab;
    	display: -ms-grid;
    	display: grid;
    	float: left;
    	font-size: 1rem;
    	height: 13rem;
    	left: 0;
    	place-items: stretch;
    	position: absolute;
    	top: 0;
    	width: 13rem;
    	z-index: 100;
    }
    sticky-note-wrapper sticky-note:active {
    	cursor: -webkit-grabbing;
    	cursor: grabbing;
    	-webkit-user-select: none;
    	   -moz-user-select: none;
    	    -ms-user-select: none;
    	        user-select: none;
    }
    sticky-note-wrapper sticky-note.right {
    	float: right;
    }
    sticky-note-wrapper sticky-note > div {
    	-ms-grid-row: 1;
    	grid-row: 1;
    	-ms-grid-column: 1;
    	grid-column: 1;
    }
    sticky-note-wrapper sticky-note > div:nth-child(1) {
    	background-color: rgba(0, 0, 0, 0.25);
    	-webkit-box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5);
    	        box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5);
    	display: -ms-grid;
    	display: grid;
    	margin: 2rem 1rem 0.25rem 0.36rem;
    	width: calc(100% - 1rem);
    }
    sticky-note-wrapper sticky-note > div:nth-child(2) {
    	clip-path: url(#stickyClip);
    	display: -ms-grid;
    	display: grid;
    	font-family: "Kalam", cursive;
    	font-style: 1rem;
    	font-weight: 300;
    	line-height: 1.25rem;
    	padding: 1rem;
    	place-items: center;
    	text-align: center;
    }
    sticky-note-wrapper sticky-note > div:nth-child(2) > * {
    	font-family: "Kalam", cursive !important;
    	font-style: normal !important;
    	font-weight: 300 !important;
    }
    @media screen and (max-width: 1024px) {
    	sticky-note-wrapper sticky-note > div:nth-child(2) {
    		max-width: 13rem;
    		min-width: 13rem;
    		width: 1rem;
    	}
    }
    @media screen and (max-width: 768px) {
    	sticky-note-wrapper sticky-note > div:nth-child(2) {
    		font-size: 1.75rem;
    		max-width: 21rem;
    		min-height: 21rem;
    	}
    }
    @media screen and (max-width: 640px) {
    	sticky-note-wrapper sticky-note > div:nth-child(2) {
    		font-size: 2.5rem;
    		max-width: 26rem;
    		min-height: 26rem;
    	}
    }
    sticky-note-wrapper sticky-note > div:nth-child(2) {
    	background: -webkit-gradient(linear, left top, left bottom, from(#ffffdd), color-stop(2%, #ffffd3), color-stop(12%, #ffffd3), color-stop(75%, #ffffc9), to(#ffffba));
    	background: linear-gradient(180deg, #ffffdd 0%, #ffffd3 2%, #ffffd3 12%, #ffffc9 75%, #ffffba 100%);
    }
    sticky-note-wrapper sticky-note.blue > div:nth-child(2) {
    	background: -webkit-gradient(linear, left top, left bottom, from(#9dddec), color-stop(2%, #94daea), color-stop(12%, #94daea), color-stop(75%, #8bd7e8), to(#7fd3e6));
    	background: linear-gradient(180deg, #9dddec 0%, #94daea 2%, #94daea 12%, #8bd7e8 75%, #7fd3e6 100%);
    }
    sticky-note-wrapper sticky-note.pink > div:nth-child(2) {
    	background: -webkit-gradient(linear, left top, left bottom, from(#fa7c93), color-stop(2%, #fa728b), color-stop(12%, #fa728b), color-stop(75%, #fa6883), to(#f95977));
    	background: linear-gradient(180deg, #fa7c93 0%, #fa728b 2%, #fa728b 12%, #fa6883 75%, #f95977 100%);
    }
    sticky-note-wrapper sticky-note.green > div:nth-child(2) {
    	background: -webkit-gradient(linear, left top, left bottom, from(#c5fcc9), color-stop(2%, #bbfbc0), color-stop(12%, #bbfbc0), color-stop(75%, #b1fab7), to(#a3faaa));
    	background: linear-gradient(180deg, #c5fcc9 0%, #bbfbc0 2%, #bbfbc0 12%, #b1fab7 75%, #a3faaa 100%);
    }
    sticky-note-wrapper:has(sticky-note:hover) {
    	background-color: #ffffd3;
    	border: 1px solid black;
    }
    sticky-note-wrapper:has(sticky-note.yellow:hover) {
    	background-color: #ffffd3;
    }
    sticky-note-wrapper:has(sticky-note.blue:hover) {
    	background-color: #94daea;
    }
    sticky-note-wrapper:has(sticky-note.pink:hover) {
    	background-color: #fa728b;
    }
    sticky-note-wrapper:has(sticky-note.green:hover) {
    	background-color: #bbfbc0;
    }

     //-		DS2 core (c) 2024 Alexander McIlwraith
    //-		Licensed under CC BY-SA 4.0

    @use 'sass:color';
    @use "sass:map";
    @use 'sass:list';
    @import url('https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap');

    $sticky-colors: (
    	"yellow": #ffffd3,
    	"blue": #94daea,
    	"pink": #fa728b,
    	"green": #bbfbc0 ) !default;

    @mixin sticky-note {
    	sticky-note-wrapper {
    		box-sizing: border-box;

    		border: 1px solid transparent;
    		border-radius: 50%;
    		display: inline-block;
    		height: .5rem;
    		position: relative;
    		width: .5rem;
    		& * {
    			box-sizing: border-box;
    		}
    		sticky-note {
    			cursor: grab;
    			display: grid;
    			float: left;
    			font-size: 1rem;
    			height: 13rem;
    			left: 0;
    			place-items: stretch;
    			position: absolute;
    			top: 0;
    			width: 13rem;
    			z-index: 100;

    			&:active {
    				cursor: grabbing;
    				user-select: none;
    			}

    			@media screen and (max-width: 1024px) {
    				//width: 15rem;
    				// background-color: green;
    			}
    			@media screen and (max-width: 768px) {
    				//width: 20rem;
    				// background-color: blue;
    			}
    			@media screen and (max-width: 640px) {
    				//width: 30rem;
    				// background-color: yellow;
    			}
    			&.right {
    				float: right;
    			}
    			@content;

    			> div {
    				grid-row: 1;
    				grid-column: 1;
    				&:nth-child(1) {
    					background-color: rgba(0, 0, 0, 0.25);
    					box-shadow: -2px 2px 15px 0 rgba(0, 0, 0, 0.5);
    					display: grid;
    					margin: 2rem 1rem .25rem .36rem;
    					width: calc(100% - 1rem);

    				}
    				&:nth-child(2) {
    					clip-path: url(#stickyClip);
    					display: grid;
    					font-family: "Kalam", cursive;
    					font-style: 1rem;
    					font-weight: 300;
    					line-height: 1.25rem;
    					padding: 1rem;
    					place-items: center;
    					text-align: center;
    					// not adding this because maybe we want the sticky note text to be able to be selected and copied.
    					// user-select: none;
    					> * {
    						font-family: "Kalam", cursive !important;
    						font-style: normal !important;
    						font-weight: 300 !important;
    					}

    					@media screen and (max-width: 1024px) {
    						max-width: 13rem;
    						min-width: 13rem;
    						width: 1rem;
    					}
    					@media screen and (max-width: 768px) {
    						font-size: 1.75rem;
    						max-width: 21rem;
    						min-height: 21rem;
    					}
    					@media screen and (max-width: 640px) {
    						font-size: 2.5rem;
    						max-width: 26rem;
    						min-height: 26rem;
    					}
    				}
    			}

    			// default colour
    			> div:nth-child(2) {
    				$sticky-color: nth(map.values($sticky-colors), 1);
    				background: linear-gradient(
    					180deg,
    					lighten($sticky-color, 2%) 0%,
    					$sticky-color 2%,
    					$sticky-color 12%,
    					darken($sticky-color, 2%) 75%,
    					darken($sticky-color, 5%) 100%
    				);
    			}
    			// all class colors
    			@each $class, $sticky-color in $sticky-colors {
    				&.#{$class} > div:nth-child(2) {
    					@if $class != nth(map.keys($sticky-colors), 1) {
    						background: linear-gradient(
    							180deg,
    							lighten($sticky-color, 2%) 0%,
    							$sticky-color 2%,
    							$sticky-color 12%,
    							darken($sticky-color, 2%) 75%,
    							darken($sticky-color, 5%) 100%
    						);
    					}
    				}
    			}
    		}
    		&:has(sticky-note:hover) {
    			background-color: #{nth(map.values($sticky-colors), 1)};
    			border: 1px solid black;

    		}
    		@each $class, $sticky-color in $sticky-colors {
    			&:has(sticky-note.#{$class}:hover) {
    				background-color: $sticky-color;
    			}
    		}
    	}
    }

     //-		DS2 core (c) 2024 Alexander McIlwraith
    //-		Licensed under CC BY-SA 4.0

    const font = {
    	size: 0
    }

    const pos = {
    	x: 0,
    	y: 0
    }

    function drag(sticky) {
    	sticky.onmousedown = event => {
    		// get the position within the sticky
    		pos.x = (event.clientX - sticky.offsetLeft);
    		pos.y = (event.clientY - sticky.offsetTop);

    		// on mouse move, move the sticky to the position, minus the offset, of the mouse
    		document.onmousemove = documentEvent => {
    			sticky.style.top = (documentEvent.clientY - pos.y) + 'px';
    			sticky.style.left = (documentEvent.clientX - pos.x) + 'px';
    			sticky.setAttribute("moved", "true");
    		}
    		// when done, remove mouse move and mouse up handlers.
    		document.onmouseup = () => {
    			document.onmouseup = null;
    			document.onmousemove = null;
    		}
    	}
    }

    function waitForElement(selector) {
        return new Promise(resolve => {
            if (document.querySelector(selector)) {
                return resolve(document.querySelector(selector));
            }

            const observer = new MutationObserver(mutations => {
                if (document.querySelector(selector)) {
                    observer.disconnect();
                    resolve(document.querySelector(selector));
                }
            });

            // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336
            observer.observe(document.body, {
                childList: true,
                subtree: true
            });
        });
    }

    const checkBottom = (attach) => {
    	// check if top or bottom
    	if (attach.y < 0) {
    		attach.ys = "bottom";
    		attach.y = attach.y * -1;
    	}
    }

    const setStickyPostions = (s, attach) => {
    		// set
    		s.style[attach.ys] = `${attach.y}px`;
    		s.style[attach.xs] = `${attach.x}px`;
    		s.style.display = "grid";
    }

    const css = (el, attr) => {
    	let st = ""
    	Object.entries(attr).forEach(val => {
    		const [key, value] = val;
      		st += `${key}: ${value}; `;
    	})
      	el.setAttribute("style",st.trim());
    }

    const calculateStickyPosition = (s) => {
    	let float = s.getAttribute("float");
    	let p = s.parentNode.getBoundingClientRect()
    	switch (float) {
    		case "left":
    			css(s, {left: (p.left * -1) + "px"})
    			break;
    		case "right":
    			css(s, { left: (Math.max(document.documentElement.clientWidth || 0, window.innerWidth || 0) - p.left - s.offsetWidth - (font.size * 2)) + "px" });
    			break;
    	}

    	let offset = s.getAttribute("offset");
    	if (offset !== null) {
    		offset = offset.trim().split(" ");
    		css(s, {top: offset[0], left: offset[1] })
    	}
    }

    export function init(p = document){
    	font.size = parseFloat(getComputedStyle(document.documentElement).fontSize.replace("px",""));

    	p.querySelectorAll("sticky-note").forEach((s) => {
    		if (s.querySelectorAll("svg").length == 0) {

    			let wrapper = document.createElement("sticky-note-wrapper");

    			s.parentNode.insertBefore(wrapper, s);
        		wrapper.appendChild(s);

    			s.setAttribute("content", s.innerHTML.replace(/"/g, "\""));
    			s.innerHTML = `${s.innerHTML}`;
    		}
    		calculateStickyPosition(s);
    		drag(s);
    		s.ondblclick = (e) => {
    			if (e.ctrlKey) {
    				calculateStickyPosition(s);
    			} else {
    				// add one click select
    			}
    		}
    	})

    	window.onresize = () => {
    		font.size = parseFloat(getComputedStyle(document.documentElement).fontSize.replace("px",""));
    		let stickies = p.querySelectorAll("sticky-note");
    		stickies.forEach((s) => {
    			calculateStickyPosition(s);
    		});
    	}
    }