# p-cool
**Repository Path**: mirrors_WebReflection/p-cool
## Basic Information
- **Project Name**: p-cool
- **Description**: Pretty Cool Elements
- **Primary Language**: Unknown
- **License**: ISC
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2021-08-09
- **Last Updated**: 2026-01-03
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Pretty Cool Elements
**Social Media Photo by [Jamison McAndie](https://unsplash.com/@jamomca) on [Unsplash](https://unsplash.com/)**
This module is a follow up of [this Medium post](https://webreflection.medium.com/about-web-components-cc3e8b4035b0), and it provides element mixins/behaviors, through class names, without names clashing.
### Features
* it addresses every single point touched in the Medium's post:
* no name clashing
* multiple mixins/behaviors attached/detached at any time
* native Custom Elements builtin callbacks, associated to mixins/behaviors
* it's **S**erver **S**ide **R**endering compatible out of the box
* it uses all the DOM primitives without needing an extra attribute (bloat-free layouts)
* it's semantically bound with element's view (their classes and their dedicated style)
* it's graceful enchancement out of the box, based on builtin extends
* it provides a robust polyfilled version through [vanilla-elements](https://github.com/WebReflection/vanilla-elements#readme)
#### Example
```js
import {define} from 'p-cool';
define('my-div', {
// to know when a behavior is attached or detached via class
attachedCallback(element) {},
detachedCallback(element) {}, // see ## About Callbacks
// to observe connected/disconnected lifecycle
connectedCallback(element) {},
disconnectedCallback(element) {},
// to observe specific attributes (omit to observe them all)
observedAttributes: ['some-attribute'],
// to know when observed attributes changed
attributeChangedCallback(element, name, oldValue, newValue) {},
});
```
```html
`, and `
`, or `` are all valid, already registered, builtin extends, that brings mixins/behaviors to any element, and through their class name, as long as one, or mixin, is defined/attached, through the `define(name, mixin)` module's export.
```html
Hero
```
To implement an *element extend*, the `` *Custom Element* is registered too, so that a page could be defined by non-builtin extends, with mixins/behaviors attached when, and if, needed.
```html
...
```
## About Callbacks
attachedCallback
This callback is granted to be invoked only *once*, and *before* any other callback, whenever a mixin/behavior is attached through the element's class, somehow simulating what a `constructor` would do with Custom Elements.
This callback is ideal to add related event listeners, setup an element for the specific mixin/behavior, and so on.
Please note that if a mixin/behavior is detached, and then re-attached, this callback *will* be invoked again.
attributeChangedCallback
If any `observedAttributes` is specified, or if there is an `attributeChangedCallback`, this is invoked every time observed attributes change.
Like it is for *Custom Elements*, this callback is invoked, after a mixin/behavior is attached, hence *after* `attachedCallback`, but *before* `connectedCallback`.
This callback is also invoked during the element lifecycle, whenever observed attributes change, providing the `oldValue` and the `newValue`.
Both values are `null` if there was not attribute, or if the attribute got removed, replicating the native *Custom Element* behavior.
connectedCallback
This callback is granted to be invoked *after* an element gets a new mixin/behavior, if the element is already live, and every other time the element gets moved or re-appended on the DOM, exactly like it is for native *Custom Elements*.
Please note that when a mixin/behavior is attached, and there are observed attributes, this callback will be invoked *after* `attributeChangedCallback`.
disconnectedCallback
This callback is granted to be invoked when an element gets removed from the DOM, and it would never trigger if the `connectedCallback` didn't happen already.
Both callbacks are the ideal place to attach, on *connected*, and remove, on *disconnected*, timers, animations, or idle related callbacks, as even when elements get trashed, both callbacks are granted to be executed, and in the right order of events.
detachedCallback
This callback is **not granted to be invoked** if an element get trashed, but it's granted to be invoked *after* `disconnectedCallback`, if a mixin/behavior is removed from an element.
Please note that this callback is *not* really useful for elements that might be, or may not be, trashed, because there is no way to use a *FinalizationRegistry* and pass along the `element`, but it's very hando for those elements that never leave the DOM, but might change, over time, their classes, hence their mixins/behaviors.
```js
import {define} from 'p-cool';
define('mixin', {
attachedCallback(element) {
console.log('mixin attached');
},
detachedCallback(element) {
console.log('mixin detached');
}
});
// example
document.body.innerHTML = `
First
Second
`;
// logs "mixin attached" twice
// will **not** "mixin detached"
first.remove();
// it **will** log "mixin detached"
second.classList.remove('mixin');
```
## About Exports
This module offers the following exports:
* `p-cool` with a `define(name, mixin)` export that *does not polyfill Safari*
* `p-cool/min` with a minified `define(name, mixin)` export that *does not polyfill Safari*
* `p-cool/poly` with a minified `define(name, mixin)` export that also *does polyfill Safari*
* `p-cool/behaviors` with the internally used `define` and `behaviors` exports, plus constants, useful to potentially create other libraries or utilities on top of the same logic
The `https://unpkg.com/p-cool` points at the minified `/poly` variant, useful to quickly test, or develop, with this module.
## Compatibility
Every ES2015+ compatible browser out of the box, including Safari/WebKit based browsers in the *poly* version.