Code Monkey home page Code Monkey logo

named-slots's Introduction

Skate

Build Status Downloads per month Join the chat at https://gitter.im/skatejs/skatejs Follow @skate_js on Twitter

Skate is a functional reactive abstraction over the web component standards as a set of packages that enables you to write small, fast and scalable web components using popular view libraries such as React, Preact and LitHTML.

  • ๐ŸŒ Cross-framework compatible components.
  • โš›๏ธ Render components using your favourite view library, or none at all.
  • ๐Ÿ‘‘ Guided conventions for best-practices when reflecting between, and reacting to attributes, properties and events.
  • ๐ŸŒŸ Full TypeScript support.
  • ๐Ÿ“š Docs https://skatejs.netlify.com.

Getting started

The simplest way to get up and running is to start with a pre-configured element such as @skatejs/element-lit-html.

npm i @skatejs/element-lit-html

Simple example

import Element, { html } from '@skatejs/element-lit-html';

export default class extends Element {
  static get props() {
    return {
      name: String
    };
  }
  render() {
    return html`
      Hello, ${this.name}!
    `;
  }
}

Other examples

  1. Todo list

Cli

There's a CLI to get you up and running: https://skatejs.netlify.com/packages/cli.

$ npm i -g @skatejs/cli
$ skatejs

Polyfills

Skate builds upon the Custom Elements and the Shadow DOM standards. It is capable of operating without the Shadow DOM โ€” it just means you don't get any encapsulation of your component's HTML or styles. It also means that it's up to you to provide a way to project content (i.e. <slot>). It's highly recommended you use Shadow DOM whenever possible.

Though most modern browsers support these standards, some still need polyfills to implement missing or inconsistent behaviours for them.

For more information on the polyfills, see the web components polyfill documentation, emphasis on the caveats.

Browser Support

Skate supports all evergreens and IE11, and is subject to the browser support matrix of the polyfills.

Backers

Support us with a monthly donation and help us continue our activities. Become a backer!

Sponsors

Become a sponsor and get your logo on our README on Github with a link to your site. Become a sponsor!

named-slots's People

Contributors

adevnadia avatar bengummer avatar bqx avatar bradleyayers avatar joscha avatar jpnelson avatar lukebatchelor avatar npmcdn-to-unpkg-bot avatar ryansolid avatar treshugart avatar zpetch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

named-slots's Issues

Do not slot empty or whitespace-only text nodes.

I don't want to have to do this, but I don't know of a good algorithm to determine if whitespace should be part of a slot. The problem comes when you write HTML; your indentation and new lines get treated as light DOM and slotted into a default slot unless you either require a named slot, or do this.

Pull in WeakMap poly

We are using the WeakMap polyfill from webcomponents.js for Skate in case there is no MutationObserver. It makes sense to use the same one here instead of providing our own implementation.

Update README to reflect current polyfilled state.

Some of the members listed as not yet polyfilled (check source).

We should also:

  • Simplify the lists. Maybe remove the headings from the lists and let the interface prefix do the talking instead.
  • Add a note about polyfilling parentNode noting how it is polyfilled and why, noting caveats.
  • Should add notes about CSS, events - basically any non-element API - will probably not be polyfilled as this is strictly a general element API polyfill that should serve common use-cases where it makes sense and the need for the API isn't outweighed by implications such as performance and complexity.

removeChild doesn't delete link to parent node

For some browsers parent of a node is still available after this node was removed from that parent.
I.e. something like this is failing:

let div = document.createElement('div'); div.appendChild(host); host.parentNode.removeChild(host); expect(host.parentNode).to.equal(null);

Bower Install broken

bower.json sets the entry point to the dist folder. A recent commit added it to the gitignore removing it from the install.

<style> elements are handled incorrectly when set via .innerHTML

This happens because of the following line in the parse function: const parsed = parser.parseFromString(html, 'text/html').body;

It turns out that the DOMParser will try to put the <style> element in the <head>, so instead of the <style> element this will return nothing.

It looks like wrapping the <style> element in a <div> will keep it in the body, so a simple solution would be to wrap the html in a container element before parsing it.

Publish 0.1.6 on NPM

That part of the release failed because I do not have collaborator permission for this project

'writable' for polyfilled properties

Polyfilled properties don't have 'writable' attribute. Because of that it's impossible to reassign value of the property using assign operator.

innerHTML / textContent on normal nodes should clean up descandants

If you set innerHTML on an ordinary node (not a host, slot or shadow root), any descendants that have been polyfilled will not be cleaned up. Weak maps should be fine, but if there's any references to these nodes, things like assignedSlot and parentNode won't be reset to null.

The only real way to do this would be to override innerHTML and textContent at the prototype level to clean up descendants.

This should be investigated as to whether or not this is even possible because of the WebKit bug around not being able to get native accessors.

Add function that does the same thing as attachShadow()

It should:

  • not be polyfilled on the Element prototype, rather, it should be its own function
  • allow { mode } to be specified to either 'open' or 'closed'
  • be the default import

This also includes:

  • modifying the render function so that it uses this new function internally
  • the src/host/polyfill is no longer the default export
import attachShadow from 'skatejs-named-slots';

const elem = document.createElement('my-element');
attachShadow(elem, { mode: 'open' });

If mode is open:

  • a shadowRoot property should be defined on the element
  • assignedSlot should return the assigned slot on a light DOM node

If mode is closed:

  • a shadowRoot property should return null on the element
  • assignedSlot should not return null on a light DOM node (this should be the default on any node)

slot can't be child of any other element

When I construct a slot like this:

host = document.createElement('div');
root = host.attachShadow({ mode: 'closed' });
parent = create('div');
slot = create('slot');

root.appendChild(parent);
parent.appendChild(slot);

I'd expect to be able to distribute to the nested slot, but this is not the case.

I believe it's to do with registering the slot, this order:

parent.appendChild(slot);
root.appendChild(parent);

works.

I have a solution for this, but it'd be good to make sure it's on the right track. It'll be on a branch that I'll post here.

Polyfill Text interface for relevant DOM methods / properties.

Currently the Textinterface isn't polyfilled, only HTMLElement is. Due to WebKit, we can't polyfill everything at the Node level so we must selectively patch the interfaces at the highest point in the prototype chain. This means Text needs to be polyfilled with the methods and properties that it shares with HTMLElement

To reproduce the issue, create an element with a shadow root that has an text node between two element nodes in the light DOM, but where the text node gets projected to a different spot than the element nodes. When using previousSibling and nextSibling, it should currently return null. Once polyfilled, it should return the element nodes.

https://developer.mozilla.org/en/docs/Web/API/Text

Polyfill more members

Add polyfills for more easy-to-polyfill and fairly common items:

  • parentElement
  • nextSibling
  • nextElementSibling
  • previousSibling
  • previousElementSibling

SVG elements aren't polyfilled

Test to reproduce:

describe('SVGElement', function () {
  it('should be polyfilled', function () {
    const div = document.createElement('div');
    const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    div.attachShadow({ mode: 'open' });
    div.shadowRoot.appendChild(document.createElement('slot'));
    div.appendChild(svg);
    expect(svg.parentNode).to.equal(div);
  });
});

We probably don't need to test all methods and properties like we do on HTMLElement, but we should ensure that the polyfilled methods on SVGElement equal the methods on HTMLElement.

Ability to specify fallback content.

We should be able to give a slot content that it will display if there's no slotted nodes.

#shadow-root
  <slot>
    <p>This will be displayed if there's no slotted nodes.</p>
  </slot>

The slot element should have polyfilled properties and methods that work with its fallback content rather than the slotted content:

  • Element.innerHTML
  • Element.outerHTML
  • Node.appendChild()
  • Node.childNodes
  • Node.firstChild
  • Node.hasChildNodes()
  • Node.insertBefore()
  • Node.lastChild
  • Node.removeChild()
  • Node.replaceChild()
  • Node.textContent
  • ParentNode.childElementCount
  • ParentNode.children
  • ParentNode.firstElementChild
  • ParentNode.lastElementChild

It's likely that these can just proxy a document fragment that's stored as data for the node. However, the constraint placed on this is that the slotting algorithm used to distribute content to a slot must only use methods. This is because we are overriding all related properties and there's a WebKit bug that prevents Object.getOwnPropertyDescriptor() from returning a valid descriptor for native prototypes so this may not be possible at all.

Write tests for dom parser against special tags such as <tr> and </td>.

Currently if you set innerHTML to a <table> and you specify special table elements, they'll be wrapped in a <div> due to #46 which is a necessary fix for <style> tags.

We'll probably end up needing to test the incoming HTML string to see if it starts with a special tag, and if so, wrap it accordingly.

Note: this is only necessary for WebKit because of the property accessor issue.

Improve distribution performance.

Performance could be better when distributing / undistributing nodes into slots. It'd be ideal to get ops / sec on the perf tests to be above 100k / sec if possible.

There's 3 areas to look:

  1. In src/shadow/distribute. The distribute() and undistribute() functions could do less work to figure out the host and root nodes of the node that was passed in. There may also be a faster way to find where the node should go rather than looking at the nextSibling.
  2. In src/shadow/polyfill, instead of going through all light DOM nodes on the host and not doing anything for ones that have alreayd been slotted, we could keep a cache of light DOM that still needs distribution when they're added in src/host/polyfill and then remove them once they're distributed.
  3. Distribution may be able to be debounced and all light dom nodes needing distribution could be moved at once. This could be done in combination with 2, but there may be faster ways to achieve this. The tests currently look for side-effects sync, so that just needs to be kept in mind as needing a refactor before, or at the same time as doing this.

[question] Is it possible to force the polyfill over native shadowDom?

My case. I'm preparing a set of wc using shadowDom. I am using regex to "port" styles using :host, ::slotted, etc.. to the shadow_root. Everything works well, chrome (native), firefox, edge, and safari, but with safari (preview and nightly) I'm getting problems with "display: flex" on de wc. It seems that doesn't work.
So, my fear is to use the polyfill and feel that everything seems to work properly. But suddenly the native shadowDom it is activated on Safari and because bugs, or different implementantion of the specs, problems would arise.
My question is if it would be possible to force the polyfill over native so I can control when to switch to native implementation.

Thanks!!

Slots not scoped to shadow roots

If one shadow root contains an element with a shadow root and both shadow roots have a default slot - or slot with the same name - then the content projected into the outer shadow root will get slotted into the first slot element that is found. This means if the inner shadow root's slot comes before the outer's, then it will get the content even though it belongs to another shadow root. This is because we don't polyfill querySelectorAll() and we use that to find slots.

Instead, we should walk the tree and discard any slots that don't belong to the current shadow root.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.