mirror of https://github.com/status-im/consul.git
Remove shadow-template/host and related components
This commit is contained in:
parent
b34244c62d
commit
6a4cd42a2b
|
@ -1,87 +0,0 @@
|
|||
# CustomElement
|
||||
|
||||
A renderless component to aid with the creation of HTML custom elements a.k.a
|
||||
WebComponents.
|
||||
|
||||
All of the CustomElement component arguments are only used at construction
|
||||
time (within the components constructor) therefore they are, by design, static.
|
||||
You shouldn't be dynamically updating these values at all. They are only for
|
||||
type checking and documention purposes and therefore once defined/hardcoded
|
||||
they should only change if you as the author wishes to change them.
|
||||
|
||||
The component is built from various other components, also see their documentaton
|
||||
for further details (`<ShadowHost />`, `<ShadowTemplate />`).
|
||||
|
||||
```hbs preview-template
|
||||
<CustomElement
|
||||
@element="x-component"
|
||||
@attrs={{array
|
||||
(array 'type' '"awesome" | "sauce"' 'awesome' 'Set the type of the x-component')
|
||||
(array 'x' 'number' 0 'The x-ness of the x-component')
|
||||
}}
|
||||
@cssprops={{array
|
||||
(array '--awesome-x-sauce' 'length' '[x]' 'Makes the x-ness of the sauce available to CSS, automatically synced/tracked from the x attributes')
|
||||
(array '--awesome-color' 'color' undefined 'This CSS property can be used to set the color of the awesome')
|
||||
}}
|
||||
@cssparts={{array
|
||||
(array 'base' 'Style base from The Outside via ::part(base)')
|
||||
}}
|
||||
@slots={{array
|
||||
(array 'header' "You'll want to document the slots also")
|
||||
(array '' 'Including the default slot')
|
||||
}}
|
||||
as |custom element|>
|
||||
<x-component
|
||||
{{did-insert custom.connect}}
|
||||
{{will-destroy custom.disconnect}}
|
||||
aria-hidden="true"
|
||||
...attributes
|
||||
>
|
||||
<custom.Template
|
||||
@styles={{css-map
|
||||
}}
|
||||
>
|
||||
<div part="base"
|
||||
data-x={{element.attrs.x}}
|
||||
data-type={{element.attrs.type}}
|
||||
>
|
||||
<slot name="header"></slot>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</custom.Template>
|
||||
</x-component>
|
||||
</CustomElement>
|
||||
|
||||
```
|
||||
|
||||
## Arguments
|
||||
|
||||
All `descriptions` in attributes will be compiled out at build time as well as the `@description` attribute itself.
|
||||
|
||||
| Attribute | Type | Default | Description |
|
||||
| :------------ | :------------- | :------ | :------------------------------------------------------------------------- |
|
||||
| element | string | | The custom tag to be used for the custom element. Must include a dash |
|
||||
| description | string | | Short 1 line description for the element. Think "git commit title" style |
|
||||
| attrs | attrInfo[] | | An array of attributes that can be used on the element |
|
||||
| slots | slotsInfo[] | | An array of slots that can be used for the element (100% compiled out) |
|
||||
| cssprops | cssPropsInfo[] | | An array of CSS properties that are relevant to the component |
|
||||
| cssparts | cssPartsInfo[] | | An array of CSS parts that can be used for the element (100% compiled out) |
|
||||
| args | argsInfo[] | | An array of Glimmer arguments used for the component (100% compiled out) |
|
||||
|
||||
## Exports
|
||||
|
||||
### custom
|
||||
|
||||
| Attribute | Type | Description |
|
||||
| :--------- | :------- | :---------------------------------------------------------------------------------- |
|
||||
| connect | function | A did-insert-able callback for tagging an element to be used for the custom element |
|
||||
| disconnect | function | A will-destroy-able callback for destroying an element used for the custom element |
|
||||
|
||||
### element
|
||||
|
||||
| Attribute | Type | Description |
|
||||
| :--------- | :------- | :------------------------------------------------------------------------------- |
|
||||
| attributes | object | An object containing a reference to all the custom elements' observed properties |
|
||||
| * | | All other properties proxy through to the CustomElements class |
|
||||
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<ShadowHost as |shadow|>
|
||||
{{yield
|
||||
(hash
|
||||
root=(fn this.setHost (fn shadow.host))
|
||||
connect=(fn this.setHost (fn shadow.host))
|
||||
Template=shadow.Template
|
||||
disconnect=(fn this.disconnect)
|
||||
)
|
||||
this.element
|
||||
}}
|
||||
</ShadowHost>
|
|
@ -1,189 +0,0 @@
|
|||
import Component from '@glimmer/component';
|
||||
import { action } from '@ember/object';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { assert } from '@ember/debug';
|
||||
|
||||
const ATTRIBUTE_CHANGE = 'custom-element.attributeChange';
|
||||
const elements = new Map();
|
||||
const proxies = new WeakMap();
|
||||
|
||||
const typeCast = (attributeInfo, value) => {
|
||||
let type = attributeInfo.type;
|
||||
const d = attributeInfo.default;
|
||||
value = value == null ? attributeInfo.default : value;
|
||||
if (type.indexOf('|') !== -1) {
|
||||
assert(
|
||||
`"${value} is not of type '${type}'"`,
|
||||
type
|
||||
.split('|')
|
||||
.map((item) => item.replaceAll('"', '').trim())
|
||||
.includes(value)
|
||||
);
|
||||
type = 'string';
|
||||
}
|
||||
switch (type) {
|
||||
case '<length>':
|
||||
case '<percentage>':
|
||||
case '<dimension>':
|
||||
case 'number': {
|
||||
const num = parseFloat(value);
|
||||
if (isNaN(num)) {
|
||||
return typeof d === 'undefined' ? 0 : d;
|
||||
} else {
|
||||
return num;
|
||||
}
|
||||
}
|
||||
case '<integer>':
|
||||
return parseInt(value);
|
||||
case '<string>':
|
||||
case 'string':
|
||||
return (value || '').toString();
|
||||
}
|
||||
};
|
||||
|
||||
const attributeChangingElement = (name, Cls = HTMLElement, attributes = {}, cssprops = {}) => {
|
||||
const attrs = Object.keys(attributes);
|
||||
|
||||
const customClass = class extends Cls {
|
||||
static get observedAttributes() {
|
||||
return attrs;
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, oldValue, newValue) {
|
||||
const prev = typeCast(attributes[name], oldValue);
|
||||
const value = typeCast(attributes[name], newValue);
|
||||
|
||||
const cssProp = cssprops[`--${name}`];
|
||||
if (typeof cssProp !== 'undefined' && cssProp.track === `[${name}]`) {
|
||||
this.style.setProperty(`--${name}`, value);
|
||||
}
|
||||
|
||||
if (typeof super.attributeChangedCallback === 'function') {
|
||||
super.attributeChangedCallback(name, prev, value);
|
||||
}
|
||||
|
||||
this.dispatchEvent(
|
||||
new CustomEvent(ATTRIBUTE_CHANGE, {
|
||||
detail: {
|
||||
name: name,
|
||||
previousValue: prev,
|
||||
value: value,
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
};
|
||||
customElements.define(name, customClass);
|
||||
return () => {};
|
||||
};
|
||||
|
||||
const infoFromArray = (arr, keys) => {
|
||||
return (arr || []).reduce((prev, info) => {
|
||||
let key;
|
||||
const obj = {};
|
||||
keys.forEach((item, i) => {
|
||||
if (item === '_') {
|
||||
key = i;
|
||||
return;
|
||||
}
|
||||
obj[item] = info[i];
|
||||
});
|
||||
prev[info[key]] = obj;
|
||||
return prev;
|
||||
}, {});
|
||||
};
|
||||
const debounceRAF = (cb, prev) => {
|
||||
if (typeof prev !== 'undefined') {
|
||||
cancelAnimationFrame(prev);
|
||||
}
|
||||
return requestAnimationFrame(cb);
|
||||
};
|
||||
const createElementProxy = ($element, component) => {
|
||||
return new Proxy($element, {
|
||||
get: (target, prop, receiver) => {
|
||||
switch (prop) {
|
||||
case 'attrs':
|
||||
return component.attributes;
|
||||
default:
|
||||
if (typeof target[prop] === 'function') {
|
||||
// need to ensure we use a MultiWeakMap here
|
||||
// if(this.methods.has(prop)) {
|
||||
// return this.methods.get(prop);
|
||||
// }
|
||||
const method = target[prop].bind(target);
|
||||
// this.methods.set(prop, method);
|
||||
return method;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export default class CustomElementComponent extends Component {
|
||||
@tracked $element;
|
||||
@tracked _attributes = {};
|
||||
|
||||
__attributes;
|
||||
_attchange;
|
||||
|
||||
constructor(owner, args) {
|
||||
super(...arguments);
|
||||
if (!elements.has(args.element)) {
|
||||
const cb = attributeChangingElement(
|
||||
args.element,
|
||||
args.class,
|
||||
infoFromArray(args.attrs, ['_', 'type', 'default', 'description']),
|
||||
infoFromArray(args.cssprops, ['_', 'type', 'track', 'description'])
|
||||
);
|
||||
elements.set(args.element, cb);
|
||||
}
|
||||
}
|
||||
|
||||
get attributes() {
|
||||
return this._attributes;
|
||||
}
|
||||
|
||||
get element() {
|
||||
if (this.$element) {
|
||||
if (proxies.has(this.$element)) {
|
||||
return proxies.get(this.$element);
|
||||
}
|
||||
const proxy = createElementProxy(this.$element, this);
|
||||
proxies.set(this.$element, proxy);
|
||||
return proxy;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@action
|
||||
setHost(attachShadow, $element) {
|
||||
attachShadow($element);
|
||||
this.$element = $element;
|
||||
this.$element.addEventListener(ATTRIBUTE_CHANGE, this.attributeChange);
|
||||
|
||||
(this.args.attrs || []).forEach((entry) => {
|
||||
const value = $element.getAttribute(entry[0]);
|
||||
$element.attributeChangedCallback(entry[0], value, value);
|
||||
});
|
||||
}
|
||||
|
||||
@action
|
||||
disconnect() {
|
||||
this.$element.removeEventListener(ATTRIBUTE_CHANGE, this.attributeChange);
|
||||
}
|
||||
|
||||
@action
|
||||
attributeChange(e) {
|
||||
e.stopImmediatePropagation();
|
||||
// currently if one single attribute changes
|
||||
// they all change
|
||||
this.__attributes = {
|
||||
...this.__attributes,
|
||||
[e.detail.name]: e.detail.value,
|
||||
};
|
||||
this._attchange = debounceRAF(() => {
|
||||
// tell glimmer we changed the attrs
|
||||
this._attributes = this.__attributes;
|
||||
}, this._attchange);
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
<!-- START component-docs:@tagName -->
|
||||
# DisclosureCard
|
||||
<!-- END component-docs:@tagName -->
|
||||
|
||||
```hbs preview-template
|
||||
|
||||
<figure>
|
||||
|
||||
<figcaption>
|
||||
Use the component
|
||||
</figcaption>
|
||||
|
||||
<DisclosureCard as |disclosure|>
|
||||
|
||||
<header>
|
||||
<h4>api-service-1</h4>
|
||||
</header>
|
||||
<Consul::Bucket::List
|
||||
@item={{hash
|
||||
Namespace="different-nspace"
|
||||
Partition="different-partition"
|
||||
}}
|
||||
@nspace={{'nspace'}}
|
||||
@partition={{'partition'}}
|
||||
/>
|
||||
<DistributionMeter
|
||||
type="linear"
|
||||
as |meter|>
|
||||
<meter.Meter class="warning" percentage="50" />
|
||||
<meter.Meter class="critical" percentage="30" />
|
||||
</DistributionMeter>
|
||||
|
||||
<disclosure.Details
|
||||
|
||||
as |details|>
|
||||
<Consul::Bucket::List
|
||||
@item={{hash
|
||||
Namespace="different-nspace"
|
||||
Partition="different-partition"
|
||||
}}
|
||||
@nspace={{'nspace'}}
|
||||
@partition={{'partition'}}
|
||||
/>
|
||||
<DistributionMeter
|
||||
type="linear"
|
||||
as |meter|>
|
||||
<meter.Meter class="warning" percentage="80" />
|
||||
<meter.Meter class="critical" percentage="10" />
|
||||
</DistributionMeter>
|
||||
|
||||
<Consul::Bucket::List
|
||||
@item={{hash
|
||||
Namespace="different-nspace"
|
||||
Partition="different-partition"
|
||||
}}
|
||||
@nspace={{'nspace'}}
|
||||
@partition={{'partition'}}
|
||||
/>
|
||||
|
||||
<DistributionMeter
|
||||
type="linear"
|
||||
as |meter|>
|
||||
<meter.Meter class="warning" percentage="10" />
|
||||
<meter.Meter class="critical" percentage="40" />
|
||||
</DistributionMeter>
|
||||
|
||||
<Consul::Bucket::List
|
||||
@item={{hash
|
||||
Namespace="different-nspace"
|
||||
Partition="different-partition"
|
||||
}}
|
||||
@nspace={{'nspace'}}
|
||||
@partition={{'partition'}}
|
||||
/>
|
||||
|
||||
<DistributionMeter
|
||||
type="linear"
|
||||
as |meter|>
|
||||
<meter.Meter class="warning" percentage="50" />
|
||||
<meter.Meter class="critical" percentage="30" />
|
||||
</DistributionMeter>
|
||||
|
||||
</disclosure.Details>
|
||||
|
||||
<disclosure.Action
|
||||
slot="action"
|
||||
{{on 'click' disclosure.toggle}}
|
||||
>
|
||||
{{if disclosure.expanded "View less" "View more"}}
|
||||
</disclosure.Action>
|
||||
|
||||
</DisclosureCard>
|
||||
|
||||
</figure>
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
<!-- START component-docs:@attrs -->
|
||||
<!-- END component-docs:@attrs -->
|
||||
|
||||
## Arguments
|
||||
|
||||
<!-- START component-docs:@args -->
|
||||
<!-- END component-docs:@args -->
|
||||
|
||||
## Slots
|
||||
|
||||
<!-- START component-docs:@slots -->
|
||||
<!-- END component-docs:@slots -->
|
||||
|
||||
## CSS Parts
|
||||
|
||||
<!-- START component-docs:@cssparts -->
|
||||
<!-- END component-docs:@cssparts -->
|
||||
|
||||
## CSS Properties
|
||||
|
||||
<!-- START component-docs:@cssprops -->
|
||||
<!-- END component-docs:@cssprops -->
|
||||
|
||||
## Contextual Components
|
||||
|
||||
<!-- START component-docs:@components -->
|
||||
<!-- END component-docs:@components -->
|
|
@ -1,90 +0,0 @@
|
|||
<CustomElement
|
||||
@element="disclosure-card"
|
||||
@description="Block level component with extra disclosable content"
|
||||
@attrs={{array
|
||||
}}
|
||||
as |custom element|>
|
||||
<Disclosure as |disclosure|>
|
||||
<disclosure-card
|
||||
{{did-insert custom.connect}}
|
||||
{{will-destroy custom.disconnect}}
|
||||
expanded={{disclosure.expanded}}
|
||||
>
|
||||
|
||||
<custom.Template
|
||||
@styles={{css-map
|
||||
(require '/styles/base/icons/base-keyframes.css' from='/components/disclosure-card')
|
||||
(require '/styles/base/icons/icons/chevron-down/index.css' from='/components/disclosure-card')
|
||||
(require '/components/panel/index.css' from='/components/disclosure-card')
|
||||
(css "
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
slot[name='action']::slotted(button) {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
|
||||
background-color: rgb(var(--tone-gray-050));
|
||||
color: rgb(var(--tone-gray-800));
|
||||
padding-top: var(--padding-y);
|
||||
padding-bottom: var(--padding-y);
|
||||
}
|
||||
slot[name='action']::slotted(button)::after {
|
||||
transition-timing-function: linear;
|
||||
transition-duration: 300ms;
|
||||
transition-property: transform;
|
||||
--icon-name: icon-chevron-down;
|
||||
--icon-size: icon-000;
|
||||
content: '';
|
||||
}
|
||||
|
||||
:host([expanded]) slot[name='action']::slotted(button)::after {
|
||||
transform: scaleY(-100%);
|
||||
}
|
||||
|
||||
:host([expanded]) [style*='max-height'] {
|
||||
transition-duration: 50ms;
|
||||
}
|
||||
[style*='max-height'] {
|
||||
transition-timing-function: ease-out;
|
||||
transition-property: max-height;
|
||||
overflow: hidden;
|
||||
}
|
||||
.content {
|
||||
padding: var(--padding-y) var(--padding-x);
|
||||
}
|
||||
")
|
||||
}}
|
||||
>
|
||||
<div part="base"
|
||||
class={{class-map
|
||||
"panel"
|
||||
}}
|
||||
>
|
||||
<div
|
||||
{{on-resize (dom-position (array
|
||||
(array 'height' 'max-height')
|
||||
))}}
|
||||
class={{class-map
|
||||
'content'
|
||||
}}
|
||||
>
|
||||
<slot>
|
||||
</slot>
|
||||
</div>
|
||||
<hr
|
||||
class={{class-map
|
||||
'panel-separator'
|
||||
}}
|
||||
/>
|
||||
<slot name="action">
|
||||
</slot>
|
||||
</div>
|
||||
</custom.Template>
|
||||
|
||||
{{yield disclosure}}
|
||||
|
||||
</disclosure-card>
|
||||
</Disclosure>
|
||||
</CustomElement>
|
|
@ -1,83 +0,0 @@
|
|||
---
|
||||
type: custom-element
|
||||
---
|
||||
<!-- START component-docs:@tagName -->
|
||||
# DistributionMeter
|
||||
<!-- END component-docs:@tagName -->
|
||||
|
||||
<!-- START component-docs:@description -->
|
||||
A meter-like component to show a distribution of values.
|
||||
<!-- END component-docs:@description -->
|
||||
|
||||
```hbs preview-template
|
||||
<figure>
|
||||
<figcaption>
|
||||
Provide a widget so we can try switching between all types of meter
|
||||
</figcaption>
|
||||
<select
|
||||
onchange={{action (mut this.type) value="target.value"}}
|
||||
>
|
||||
<option>linear</option>
|
||||
<option>radial</option>
|
||||
<option>circular</option>
|
||||
</select>
|
||||
</figure>
|
||||
<figure>
|
||||
|
||||
<DataSource
|
||||
@src={{uri '/partition/namespace/dc-1/services'}}
|
||||
as |source|>
|
||||
{{#let
|
||||
(group-by "MeshStatus" (or source.data (array)))
|
||||
as |grouped|}}
|
||||
<DistributionMeter type={{or this.type 'linear'}} as |meter|>
|
||||
{{#each (array 'passing' 'warning' 'critical') as |status|}}
|
||||
{{#let
|
||||
(concat (percentage-of (get grouped (concat status '.length')) source.data.length) '%')
|
||||
as |percentage|}}
|
||||
<meter.Meter
|
||||
description={{capitalize status}}
|
||||
percentage={{percentage}}
|
||||
class={{class-map
|
||||
status
|
||||
}}
|
||||
as |meter|></meter.Meter>
|
||||
{{/let}}
|
||||
{{/each}}
|
||||
</DistributionMeter>
|
||||
{{/let}}
|
||||
</DataSource>
|
||||
</figure>
|
||||
```
|
||||
|
||||
## Attributes
|
||||
|
||||
<!-- START component-docs:@attrs -->
|
||||
| Attribute | Type | Default | Description |
|
||||
| :-------- | :--------------------------------- | :------ | :------------------------------------ |
|
||||
| type | "linear" \| "radial" \| "circular" | linear | The type of distribution meter to use |
|
||||
|
||||
<!-- END component-docs:@attrs -->
|
||||
|
||||
## Contextual Components
|
||||
|
||||
<!-- START component-docs:@components -->
|
||||
|
||||
### DistributionMeter::Meter
|
||||
|
||||
#### Attributes
|
||||
|
||||
| Attribute | Type | Default | Description |
|
||||
| :---------- | :----- | :------ | :----------------------------------------- |
|
||||
| percentage | number | 0 | The percentage to be used for the meter |
|
||||
| description | string | | Textual value to describe the meters value |
|
||||
|
||||
|
||||
#### CSS Properties
|
||||
|
||||
| Property | Type | Tracks | Description |
|
||||
| :---------------------- | :--------- | :----------- | :---------------------------------------------------------------- |
|
||||
| --percentage | percentage | [percentage] | Read-only alias of the percentage attribute |
|
||||
| --aggregated-percentage | percentage | | Aggregated percentage of all meters within the distribution meter |
|
||||
|
||||
<!-- END component-docs:@components -->
|
|
@ -1,32 +0,0 @@
|
|||
export default (css) => {
|
||||
return css`
|
||||
:host {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
dl {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
:host([type='linear']) {
|
||||
height: 3px;
|
||||
}
|
||||
:host([type='radial']),
|
||||
:host([type='circular']) {
|
||||
height: 300px;
|
||||
}
|
||||
:host([type='linear']) dl {
|
||||
background-color: currentColor;
|
||||
color: rgb(var(--tone-gray-100));
|
||||
border-radius: var(--decor-radius-999);
|
||||
transition-property: transform;
|
||||
transition-timing-function: ease-out;
|
||||
transition-duration: 0.1s;
|
||||
}
|
||||
:host([type='linear']) dl:hover {
|
||||
transform: scaleY(3);
|
||||
box-shadow: var(--decor-elevation-200);
|
||||
}
|
||||
`;
|
||||
};
|
|
@ -1,30 +0,0 @@
|
|||
<CustomElement
|
||||
@element="distribution-meter"
|
||||
@description="A meter-like component to show a distribution of values."
|
||||
@attrs={{array
|
||||
(array 'type' '"linear" | "radial" | "circular"' 'linear'
|
||||
'The type of distribution meter to use'
|
||||
)
|
||||
}}
|
||||
as |custom element|>
|
||||
<distribution-meter
|
||||
{{did-insert custom.connect}}
|
||||
{{will-destroy custom.disconnect}}
|
||||
...attributes
|
||||
>
|
||||
<custom.Template
|
||||
@styles={{css-map
|
||||
(require './index.css' from='/components/distribution-meter')
|
||||
}}
|
||||
>
|
||||
<dl>
|
||||
<slot></slot>
|
||||
</dl>
|
||||
</custom.Template>
|
||||
{{yield (hash
|
||||
Meter=(component 'distribution-meter/meter'
|
||||
type=element.attrs.type
|
||||
)
|
||||
)}}
|
||||
</distribution-meter>
|
||||
</CustomElement>
|
|
@ -1,29 +0,0 @@
|
|||
const parseFloatWithDefault = (val, d = 0) => {
|
||||
const num = parseFloat(val);
|
||||
return isNaN(num) ? d : num;
|
||||
};
|
||||
|
||||
export default (Component) => {
|
||||
return class extends Component {
|
||||
attributeChangedCallback(name, prev, value) {
|
||||
const target = this;
|
||||
switch (name) {
|
||||
case 'percentage': {
|
||||
let prevSibling = target;
|
||||
while (prevSibling) {
|
||||
const nextSibling = prevSibling.nextElementSibling;
|
||||
const aggregatedPercentage = nextSibling
|
||||
? parseFloatWithDefault(nextSibling.style.getPropertyValue('--aggregated-percentage'))
|
||||
: 0;
|
||||
const perc =
|
||||
parseFloatWithDefault(prevSibling.getAttribute('percentage')) + aggregatedPercentage;
|
||||
prevSibling.style.setProperty('--aggregated-percentage', perc);
|
||||
prevSibling.setAttribute('aggregated-percentage', perc);
|
||||
prevSibling = prevSibling.previousElementSibling;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
|
@ -1,80 +0,0 @@
|
|||
export default (css) => {
|
||||
return css`
|
||||
/*@import '~/styles/base/decoration/visually-hidden.css';*/
|
||||
|
||||
:host(.critical) {
|
||||
color: rgb(var(--tone-red-500));
|
||||
}
|
||||
:host(.warning) {
|
||||
color: rgb(var(--tone-orange-500));
|
||||
}
|
||||
:host(.passing) {
|
||||
color: rgb(var(--tone-green-500));
|
||||
}
|
||||
|
||||
:host {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
|
||||
transition-timing-function: ease-out;
|
||||
transition-duration: 0.5s;
|
||||
}
|
||||
dt,
|
||||
dd meter {
|
||||
animation-name: visually-hidden;
|
||||
animation-fill-mode: forwards;
|
||||
animation-play-state: paused;
|
||||
}
|
||||
|
||||
:host(.type-linear) {
|
||||
transition-property: width;
|
||||
width: calc(var(--aggregated-percentage) * 1%);
|
||||
height: 100%;
|
||||
background-color: currentColor;
|
||||
border-radius: var(--decor-radius-999);
|
||||
}
|
||||
|
||||
:host svg {
|
||||
height: 100%;
|
||||
}
|
||||
:host(.type-radial),
|
||||
:host(.type-circular) {
|
||||
transition-property: none;
|
||||
}
|
||||
:host(.type-radial) dd,
|
||||
:host(.type-circular) dd {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
:host(.type-radial) circle,
|
||||
:host(.type-circular) circle {
|
||||
transition-timing-function: ease-out;
|
||||
transition-duration: 0.5s;
|
||||
pointer-events: stroke;
|
||||
transition-property: stroke-dashoffset, stroke-width;
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: 50%;
|
||||
fill: transparent;
|
||||
stroke: currentColor;
|
||||
stroke-dasharray: 100, 100;
|
||||
stroke-dashoffset: calc(calc(100 - var(--aggregated-percentage)) * 1px);
|
||||
}
|
||||
:host([aggregated-percentage='100']) circle {
|
||||
stroke-dasharray: 0 !important;
|
||||
}
|
||||
:host([aggregated-percentage='0']) circle {
|
||||
stroke-dasharray: 0, 100 !important;
|
||||
}
|
||||
:host(.type-radial) circle,
|
||||
:host(.type-circular]) svg {
|
||||
pointer-events: none;
|
||||
}
|
||||
:host(.type-radial) circle {
|
||||
stroke-width: 32;
|
||||
}
|
||||
:host(.type-circular) circle {
|
||||
stroke-width: 14;
|
||||
}
|
||||
`;
|
||||
};
|
|
@ -1,64 +0,0 @@
|
|||
<CustomElement
|
||||
@element="distribution-meter-meter"
|
||||
@class={{require './element'
|
||||
from='/components/distribution-meter/meter'}}
|
||||
|
||||
@attrs={{array
|
||||
(array 'percentage' 'number' 0
|
||||
'The percentage to be used for the meter'
|
||||
)
|
||||
(array 'description' 'string' ''
|
||||
'Textual value to describe the meters value'
|
||||
)
|
||||
}}
|
||||
|
||||
@cssprops={{array
|
||||
(array '--percentage' 'percentage' '[percentage]'
|
||||
'Read-only alias of the percentage attribute'
|
||||
)
|
||||
(array '--aggregated-percentage' 'percentage' undefined
|
||||
'Aggregated percentage of all meters within the distribution meter'
|
||||
)
|
||||
}}
|
||||
as |custom element|>
|
||||
|
||||
<distribution-meter-meter
|
||||
{{did-insert custom.connect}}
|
||||
{{will-destroy custom.disconnect}}
|
||||
class={{class-map
|
||||
(array (concat 'type-' @type) @type)
|
||||
}}
|
||||
...attributes
|
||||
>
|
||||
<custom.Template
|
||||
@styles={{css-map
|
||||
(require '/styles/base/decoration/visually-hidden.css'
|
||||
from='/components/distribution-meter/meter')
|
||||
(require './index.css'
|
||||
from='/components/distribution-meter/meter')
|
||||
}}
|
||||
>
|
||||
<dt>{{element.attrs.description}}</dt>
|
||||
<dd aria-label={{concat element.attrs.percentage '%'}}>
|
||||
<meter min="0" max="100" value={{element.attrs.percentage}}>
|
||||
<slot>{{concat element.attrs.percentage '%'}}</slot>
|
||||
</meter>
|
||||
{{#if (or (eq @type 'circular') (eq @type 'radial'))}}
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
viewBox="0 0 32 32"
|
||||
clip-path="circle()"
|
||||
>
|
||||
<circle
|
||||
r="16"
|
||||
cx="16"
|
||||
cy="16"
|
||||
/>
|
||||
</svg>
|
||||
{{/if}}
|
||||
</dd>
|
||||
</custom.Template>
|
||||
</distribution-meter-meter>
|
||||
|
||||
</CustomElement>
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
# ShadowHost
|
||||
|
||||
`ShadowHost` is a small renderless mainly utility component for easily attaching
|
||||
ShadowDOM to any applicable DOM node. It mainly exists to provide a context for
|
||||
passing around a reference to the element to be used for the shadow template,
|
||||
but named appropriately for recognition.
|
||||
|
||||
If you are looking to write a custom element, please use the `CustomElement`
|
||||
component. If you are simply attaching ShadowDOM to a native HTML element then
|
||||
this is the component for you.
|
||||
|
||||
```hbs preview-template
|
||||
<ShadowHost as |shadow|>
|
||||
<div
|
||||
{{did-insert shadow.host}}
|
||||
>
|
||||
<shadow.Template>
|
||||
<p>hi</p>
|
||||
</shadow.Template>
|
||||
</div>
|
||||
</ShadowHost>
|
||||
```
|
||||
|
||||
## Exports
|
||||
|
||||
| Attribute | Type | Description |
|
||||
| :-------- | :---------------------- | :------------------------------------------------------------------------------- |
|
||||
| host | function | A did-insert-able callback for tagging an element to be used for the shadow root |
|
||||
| Template | ShadowTemplateComponent | ShadowTemplate component pre-configured with the shadow host |
|
|
@ -1,5 +0,0 @@
|
|||
{{yield (hash
|
||||
host=(fn this.attachShadow)
|
||||
root=this.shadowRoot
|
||||
Template=(component 'shadow-template' shadowRoot=this.shadowRoot)
|
||||
)}}
|
|
@ -1,12 +0,0 @@
|
|||
import Component from '@glimmer/component';
|
||||
import { action } from '@ember/object';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
|
||||
export default class ShadowHostComponent extends Component {
|
||||
@tracked shadowRoot;
|
||||
|
||||
@action
|
||||
attachShadow($element) {
|
||||
this.shadowRoot = $element.attachShadow({ mode: 'open' });
|
||||
}
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
# ShadowTemplate
|
||||
|
||||
A component to aid creating ShadowDOM based components (when required), heavily
|
||||
inspired by the upcoming Declarative Shadow DOM spec, a new way to implement and
|
||||
use Shadow DOM directly in HTML.
|
||||
|
||||
Instead of passing `shadowroot="open|closed"` as you would with Declarative
|
||||
Shadow DOM we have a `@shadowRoot` argument to which you would pass the actual
|
||||
Shadow DOM element (which itself either open or closed). You can get a reference
|
||||
to this by using the `{{attach-shadow}}` modifier.
|
||||
|
||||
Additionally a `@styles` argument is made available for you to optionally
|
||||
pass completely isolated, scoped, constructable stylesheets to be used for the
|
||||
Shadow DOM tree (you can also continue to use `<style>` within the template
|
||||
itself also if necessary).
|
||||
|
||||
For the moment we'd generally use a standard div element and add Shadow DOM to
|
||||
it, but as shown in the second example, you could also use it to make
|
||||
Glimmerized native custom-elements using Declarative ShadowDOM and
|
||||
Constructable Stylesheets.
|
||||
|
||||
**Important:** As ShadowDOM elements are completely isolated please take care
|
||||
to use the features available (slots/parts etc) to make sure components built in
|
||||
this way can make use of a11y functionality, i.e. any elements having necessary
|
||||
`id` relationships for a11y reasons should be slotted to ensure that the all
|
||||
`id`s remain in the LightDOM. Native form controls such as inputs etc should
|
||||
also be slotted in order to keep them in the LightDOM to ensure that native
|
||||
form functionality continues to work.
|
||||
|
||||
Beside several advantages of isolated DOM/CSS ShadowDOM slots can also be used
|
||||
within conditionals, something which is currently not possible with
|
||||
Glimmer/Ember slots. Mixing Glimmer/Handlebars conditionals with native
|
||||
ShadowDOM slots will give you this additional feature (see truthy conditional in
|
||||
the example below).
|
||||
|
||||
```hbs preview-template
|
||||
<div
|
||||
class={{class-map
|
||||
"component-name"
|
||||
}}
|
||||
...attributes
|
||||
{{attach-shadow (set this 'shadow')}}
|
||||
>
|
||||
<ShadowTemplate
|
||||
@shadowRoot={{this.shadow}}
|
||||
@styles={{css '
|
||||
:host {
|
||||
background-color: rgb(var(--tone-strawberry-500) / 20%);
|
||||
padding: 1rem; /* 16px */
|
||||
}
|
||||
header {
|
||||
color: purple;
|
||||
}
|
||||
p {
|
||||
color: green;
|
||||
}
|
||||
|
||||
::slotted(header) {
|
||||
color: blue;
|
||||
}
|
||||
::slotted(p) {
|
||||
color: red;
|
||||
}
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
header::before {
|
||||
margin-right: 0.375rem; /* 6px */
|
||||
}
|
||||
'}}
|
||||
>
|
||||
<header part="header">
|
||||
<slot name="header">
|
||||
<h1>Default Header</h1>
|
||||
</slot>
|
||||
</header>
|
||||
<!-- Wrap the slot in a conditional -->
|
||||
{{#if true}}
|
||||
<slot name="body">
|
||||
<p>Default Body</p>
|
||||
</slot>
|
||||
{{/if}}
|
||||
<slot>
|
||||
<!-- The default slot -->
|
||||
</slot>
|
||||
</ShadowTemplate>
|
||||
</div>
|
||||
```
|
||||
|
||||
```css
|
||||
.component-name::part(header)::before {
|
||||
@extend %with-logo-consul-color-icon, %as-pseudo;
|
||||
width: 2rem; /* 32px */
|
||||
height: 2rem; /* 32px */
|
||||
}
|
||||
```
|
||||
|
||||
Example with a custom element. **Please note:** These must still be instantiated
|
||||
using Glimmer syntax i.e. `<ComponentName />` not `<component-name />` but a
|
||||
`<component-name />` element will be rendered to the DOM instead of a `<div>`.
|
||||
|
||||
```hbs preview-template
|
||||
<component-name
|
||||
...attributes
|
||||
{{attach-shadow (set this 'shadow')}}
|
||||
>
|
||||
<ShadowTemplate
|
||||
@shadowRoot={{this.shadow}}
|
||||
@styles={{css '
|
||||
header {
|
||||
color: purple;
|
||||
}
|
||||
p {
|
||||
color: green;
|
||||
}
|
||||
|
||||
::slotted(header) {
|
||||
color: blue;
|
||||
}
|
||||
::slotted(p) {
|
||||
color: red;
|
||||
}
|
||||
header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
header::before {
|
||||
margin-right: 0.375rem; /* 6px */
|
||||
}
|
||||
'}}
|
||||
>
|
||||
<header part="header">
|
||||
<slot name="header">
|
||||
<h1>Default Header</h1>
|
||||
</slot>
|
||||
</header>
|
||||
{{#if true}}
|
||||
<slot name="body">
|
||||
<p>Default Body</p>
|
||||
</slot>
|
||||
{{/if}}
|
||||
<slot>
|
||||
<!-- The default slot -->
|
||||
</slot>
|
||||
</ShadowTemplate>
|
||||
</component-name>
|
||||
```
|
||||
|
||||
```css
|
||||
component-name::part(header)::before {
|
||||
@extend %with-logo-consul-color-icon, %as-pseudo;
|
||||
width: 2rem; /* 32px */
|
||||
height: 2rem; /* 32px */
|
||||
}
|
||||
```
|
||||
## Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `shadowRoot` | `ShadowRoot` | | A reference to a shadow root (probably retrived using the `{{attach-shadow}}` modifier |
|
||||
| `styles` | `CSSResultGroup` | | Styles to be adopted by the ShadowRoot |
|
|
@ -1,6 +0,0 @@
|
|||
[id^='docfy-demo-preview-shadow-template'] .component-name::part(header)::before,
|
||||
[id^='docfy-demo-preview-shadow-template'] component-name::part(header)::before {
|
||||
@extend %with-logo-consul-color-icon, %as-pseudo;
|
||||
width: 2rem; /* 32px */
|
||||
height: 2rem; /* 32px */
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
{{#if @shadowRoot}}
|
||||
{{#in-element @shadowRoot}}
|
||||
{{#if @styles}}
|
||||
{{adopt-styles
|
||||
@shadowRoot
|
||||
@styles
|
||||
}}
|
||||
{{/if}}
|
||||
{{yield}}
|
||||
{{/in-element}}
|
||||
{{/if}}
|
|
@ -1,23 +0,0 @@
|
|||
import { setModifierManager, capabilities } from '@ember/modifier';
|
||||
|
||||
export default setModifierManager(
|
||||
() => ({
|
||||
capabilities: capabilities('3.13', { disableAutoTracking: true }),
|
||||
|
||||
createModifier() {},
|
||||
|
||||
installModifier(_state, element, { positional: [fn, ...args], named }) {
|
||||
let shadow;
|
||||
try {
|
||||
shadow = element.attachShadow({ mode: 'open' });
|
||||
} catch (e) {
|
||||
// shadow = false;
|
||||
console.error(e);
|
||||
}
|
||||
fn(shadow);
|
||||
},
|
||||
updateModifier() {},
|
||||
destroyModifier() {},
|
||||
}),
|
||||
class CustomElementModifier {}
|
||||
);
|
|
@ -1,28 +0,0 @@
|
|||
# attach-shadow
|
||||
|
||||
`{{attach-shadow (set this 'shadow')}}` attaches a `ShadowRoot` to the modified DOM element
|
||||
and pass a reference to that `ShadowRoot` to the setter function.
|
||||
|
||||
|
||||
Please note: This should be used as a utility modifier for when having access
|
||||
to the shadow DOM is handy, not really for building full blown shadow DOM
|
||||
based Web Components.
|
||||
|
||||
```hbs preview-template
|
||||
<div
|
||||
{{attach-shadow (set this 'shadow')}}
|
||||
>
|
||||
{{#if this.shadow}}
|
||||
{{#in-element this.shadow}}
|
||||
<slot name="name"></slot>
|
||||
{{/in-element}}
|
||||
{{/if}}
|
||||
<p slot="name">Hello from the shadows!</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Positional Arguments
|
||||
|
||||
| Argument | Type | Default | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| `setter` | `function` | | Usually `set` or `mut` or similar |
|
|
@ -5,7 +5,6 @@
|
|||
@import 'consul-ui/components/badge/debug';
|
||||
@import 'consul-ui/components/panel/debug';
|
||||
@import 'consul-ui/components/tile/debug';
|
||||
@import 'consul-ui/components/shadow-template/debug';
|
||||
@import 'consul-ui/components/csv-list/debug';
|
||||
@import 'consul-ui/components/horizontal-kv-list/debug';
|
||||
@import 'consul-ui/components/icon-definition/debug';
|
||||
|
|
Loading…
Reference in New Issue