Remove shadow-template/host and related components

This commit is contained in:
wenincode 2022-10-26 08:07:35 -06:00
parent b34244c62d
commit 6a4cd42a2b
20 changed files with 0 additions and 1097 deletions

View File

@ -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 |

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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 -->

View File

@ -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>

View File

@ -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 -->

View File

@ -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);
}
`;
};

View File

@ -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>

View File

@ -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;
}
}
}
};
};

View File

@ -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;
}
`;
};

View File

@ -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>

View File

@ -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 |

View File

@ -1,5 +0,0 @@
{{yield (hash
host=(fn this.attachShadow)
root=this.shadowRoot
Template=(component 'shadow-template' shadowRoot=this.shadowRoot)
)}}

View File

@ -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' });
}
}

View File

@ -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 |

View File

@ -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 */
}

View File

@ -1,11 +0,0 @@
{{#if @shadowRoot}}
{{#in-element @shadowRoot}}
{{#if @styles}}
{{adopt-styles
@shadowRoot
@styles
}}
{{/if}}
{{yield}}
{{/in-element}}
{{/if}}

View File

@ -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 {}
);

View File

@ -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 |

View File

@ -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';