Skip to content

Commit

Permalink
Initial code for tester component
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-harding committed Oct 6, 2024
1 parent 1167efb commit 5a3e752
Show file tree
Hide file tree
Showing 5 changed files with 233 additions and 15 deletions.
27 changes: 27 additions & 0 deletions demo/assets/css/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
box-sizing: border-box;
}

:root {
font-family: "Poppins", sans-serif;
font-weight: 400;
font-style: normal;
}

body {
display: grid;
grid-auto-columns: 1fr;
Expand All @@ -25,3 +31,24 @@ body {
.th-squircle {
contain: strict;
}

.tester {
}

.tester__squircle {
}

.tester__controls {
}

.tester-corner {
}

.tester-control {
}

.tester-control__label {
}

.tester-control__input {
}
5 changes: 5 additions & 0 deletions demo/assets/js/demo.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Tester, Corner, Control } from "./tester.js";

const IS_PAINT_SUPPORTED = CSS.supports("background", "paint(id)");

function main() {
loadSquircleComponent();
loadPaintWorklet();
customElements.define("th-tester", Tester);
customElements.define("th-tester-corner", Corner);
customElements.define("th-tester-control", Control);
}

async function loadPaintWorklet() {
Expand Down
152 changes: 152 additions & 0 deletions demo/assets/js/tester.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/**
* @typedef {"top-left" | "bottom-right"} Position
* @typedef {{ x: number, y: number, position: Position }} CornerEventProps
* @typedef {CustomEvent<CornerEventProps>} CornerEvent
*
* @typedef {{ value: string, aspect: string }} ControlEventProps
* @typedef {CustomEvent<ControlEventProps>} ControlEvent
*/

export class Tester extends HTMLElement {
/** @type {HTMLElement?} */
_squircle = null;

constructor() {
super();
const listen = listenPassive.bind(this);
listen("th-tester-corner", this._handleCorner);
listen("th-tester-control", this._handleControl);
}

connectedCallback() {
this._squircle = this.querySelector("th-squircle");
}

/**
* @param {CornerEvent} event
*/
_handleCorner(event) {
console.log(event);
}

/**
* @param {ControlEvent} event
*/
_handleControl(event) {
console.log(event);
}
}

export class Corner extends HTMLElement {
_isPressed = false;
_position = "";

static get observedAttributes() {
return ["position"];
}

constructor() {
super();
const listen = listenPassive.bind(this);
listen("mousedown", this._handleMouseDown);
listen("mouseup", this._handleMouseUp);
listen("mousemove", this._handleMouseMove);
}

/**
* @param {string} name
* @param {string} _
* @param {string} newValue
*/
attributeChangedCallback(name, _, newValue) {
switch (name) {
case "position": {
this._position = newValue;
break;
}
}
}

_handleMouseDown() {
this._isPressed = true;
}

_handleMouseUp() {
this._isPressed = false;
}

/**
* @param {MouseEvent} mouseEvent
*/
_handleMouseMove(mouseEvent) {
if (!this._isPressed) return;
const { movementX: x, movementY: y } = mouseEvent;
const event = new CustomEvent("th-tester-corner", {
detail: { x, y, position: this._position },
bubbles: true,
});
this.dispatchEvent(event);
}
}

export class Control extends HTMLElement {
_aspect = "";

static get observedAttributes() {
return ["aspect"];
}

constructor() {
super();
}

connectedCallback() {
const input = this.querySelector("input");
if (!(input instanceof HTMLInputElement)) {
console.warn("Expected input element");
return;
}

const listen = listenPassive.bind(this);
listen("change", this._handleChange);
}

/**
* @param {string} name
* @param {string} _
* @param {string} newValue
*/
attributeChangedCallback(name, _, newValue) {
switch (name) {
case "aspect": {
this._aspect = newValue;
break;
}
}
}

/**
* @param {InputEvent} inputEvent
*/
_handleChange(inputEvent) {
const target = inputEvent.target;
if (!(target instanceof HTMLInputElement)) return;
const value = target.value;
const event = new CustomEvent("th-tester-control", {
detail: { value, aspect: this._aspect },
bubbles: true,
});
this.dispatchEvent(event);
}
}

/**
* @this {HTMLElement}
* @param {string} name
* @param {any} handler
*/
function listenPassive(name, handler) {
this.addEventListener(name, handler.bind(this), {
passive: true,
});
}
55 changes: 40 additions & 15 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,13 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

<script
src="{{ '/assets/js/demo.js' | relative_url }}"
type="module"
async
></script>
<link
href="{{ '/assets/js/squircle-canvas.js' | relative_url }}"
rel="modulepreload"
/>
<link
href="{{ '/assets/js/squircle-houdini.js' | relative_url }}"
rel="modulepreload"
/>
<link
href="https://unpkg.com/[email protected]/worklet.min.js"
rel="modulepreload"
/>

<link
href="https://unpkg.com/[email protected]/index.css"
rel="stylesheet"
Expand All @@ -31,11 +21,46 @@
href="{{ '/assets/css/style.css' | relative_url }}"
rel="stylesheet"
/>

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap"
rel="stylesheet"
/>

<title>Squircle Demo</title>
</head>

<body>
<th-squircle></th-squircle>
<th-squircle></th-squircle>
<body class="poppins-regular">
<th-tester class="tester">
<th-tester-corner class="tester__corner"></th-tester-corner>
<th-tester-corner class="tester__corner"></th-tester-corner>
<th-squircle class="tester__squircle"></th-squircle>

<form class="tester__controls">
<th-tester-control class="tester-control">
<label class="tester-control__label" for="tester-input-radius"
>Radius</label
>
<input
class="tester-control__input"
id="tester-input-radius"
type="range"
/>
</th-tester-control>

<th-tester-control class="tester-control">
<label class="tester-control__label" for="tester-input-fill"
>Fill</label
>
<input
class="tester-control__input"
id="tester-input-fill"
type="color"
/>
</th-tester-control>
</form>
</th-tester>
</body>
</html>
9 changes: 9 additions & 0 deletions demo/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"module": "esnext",
"target": "esnext",
"strict": true,
"allowJs": true,
"checkJs": true
}
}

0 comments on commit 5a3e752

Please sign in to comment.