Giter Club home page Giter Club logo

hybrids's People

Contributors

1ntegr8 avatar au-z avatar awei01 avatar bboydflo avatar bennypowers avatar bgoscinski avatar chrmod avatar dangodev avatar dependabot[bot] avatar iahu avatar imme-emosol avatar metasean avatar nsaunders avatar pietrzakacper avatar qsppl avatar riccardoscalco avatar rschooley avatar smalluban avatar tennox avatar

Stargazers

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

Watchers

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

hybrids's Issues

render: couple thoughts about why render uses asynchronous queue to update the DOM

Hey guys, I've been using Hybrids pretty extensively for a couple months and had a question about one of the design decisions / gotchas that's bitten me a number of times. In the past, there has typically been a good reason for the choices made in Hybrids, so I imagine that may be the case here, too -- just wondering what that reason might be...

Basically, why do you wait to attach the shadowRoot until the initial render? Most custom element sample code and existing libraries attach the shadowRoot and create the shadow DOM within the element's constructor, so it is available from that component's properties and methods immediately.

In addition to the shadow DOM not being available until the component is connected, because Hybrids optimizes rendering to 60fps by potentially deferring tasks to subsequent animation frames, the shadow DOM's existence immediately following connection is non-deterministic. It may be available in the next requestAnimationFrame, or -- on slow browsers like IE11 -- it may not be available until much later.

This can cause timing issues where methods and properties may try to access shadow DOM that is not yet available. Should attempts to access non-existent shadow DOM throw an exception? Should it queue all requests and invoke them when rendering finally occurs? Should it defer the first request until rendering? The most recent request?

We can avoid these questions entirely by performing an initial render in the constructor and rendering any updates within the rAF queue. Since properties are already set in the constructor, I can't see any immediate logistical reason why the initial render needs to be delayed -- but there's probably something I'm missing.

Here's an example:

import { html, define } from 'hybrids';

define('my-custom-dialog', {
  show: (host) => (arg) => {
    console.log('show called with', arg);
    host.shadowRoot.querySelector('dialog').showModal();
  },
  render: () => html`<dialog>hello</dialog>`
});

const el = document.createElement('my-custom-dialog');
el.show(1); // throws exception -- shadowRoot is null
document.body.appendChild(el);
requestAnimationFrame(() => el.show(2)); // may or may not throw exception (depends on FPS)

Is there any chance you can move the initial render to the constructor? If not, what's the best way to work around the non-deterministic shadow DOM issue?

As always, thanks for a great library!

How to pass down a function?

Hello! First of all, I love this project. Really good work. I hope it will get the traction it deserves.

But there is one thing I cannot wrap my head around. Meaybe it would be helpful to have a kind of getting started tutorial for developing a small app. Ok here is my problem:
Say we have a parent component <todo-list> which has a property with the list of todos - lets say it is an array with strings. This <todo-list> renders for every todo in the array a child component <todo-item>. Each item has a button, which - if clicked- would remove this item from the array in <todo-list>. In React or Vue, I would just pass down a function to the child components - how would I solve this in hybrids? Maybe I am just thinking too much in the react box.. Thanks in advance!

is this library done?

maybe not the right place to ask but here I go. Is this library done? are there any plans for new features? I'm asking because I've read the docs and everything seems super easy to understand and feature complete. that's why I'm wondering

how to fire an event from client by code

Hello! First of all, I love this project. Really good work.
I just need to know , how to fire an event from client by code,
I mean :
I have a tag on html side
Which is defined with an event listener in a button onclick event .

Everything works fine when I click on button ,but I need to fire this event from client by code , something like :

var myElement = document.getElementsByTagName('simple-counter')[0];
myElement.render();

but does not work , 🆘
may you help me ?
Thanks in advance

Try to set key in get call error

emitting custom event from inner element element and attempting to set outer element property causes "Try to set key in get call" error

definition: connecting inner properties with Redux

I'm refactoring my code and making it more react-ish, so I was trying to do something like this:

  • Created state and props properties
  • Connect the component with the reducer, and the reducer state stay inside this props property

In other works, something like this:

const Component = {
  props: {
     myReducer: connect(store, (store) => store.myReducer)
  }
}

But if I do it, it's doesn't work, the inner property stays blank, but if I connect with props, it works, i'd like to know if it is a bug or a feature.

how to avoid escaping raw html?

hi! amazing lib that is hybrids.

I'm struggling with the tag literals to insert a <mark> tag in some places:

//import { html, define } from "hybrids";
  import { html, define } from 'https://unpkg.com/[email protected]/src';
//import lunr from "lunr";

function search(host, event) {
  host.query = event.target.value;
}

const FullTextSearch = {
  indexUrl: "",
  query: "",
  index: async ({ indexUrl }) =>
    lunr.Index.load(await (await fetch(indexUrl)).json()),
  results: async ({ index, query }) => query ? (await index).search(`${query}`) : [],
  render: ({ query, results }) => html`
    <input placeholder="search" type="search" oninput="${search}" />
    <ul>${html.resolve(
      results.then(
        r => html`${r.map(result => html`<li>
            <a href="${result.ref}">${result.ref}</a>
            <article>${html.resolve(fetch(result.ref).then(async content =>
                html`${extract(query, await content.text(), result.matchData.metadata)}`
            ))}</article>
        </li>`)}`
      ).catch(e => html`${e}`),
      html`…`
    )}</ul>
  `
};

function extract(query, content, metadata) {
    let positions = Object.values(metadata).flatMap((term) => Object.values(term).flatMap(t => t.position));
    return positions
        .map(([start, len]) => `[…] ${content.substring(start - 50, start + len + 50)} […]`)
        .map(fragment => fragment.replace(new RegExp(`(${query})`, 'i'), `<mark>$1</mark>`))
    ;
}

define("fulltext-search", FullTextSearch);

Not exactly sure why, but the <mark> markup is displayed as is.
Any idea how I could solve this problem?

Thanks!

Option to customize attachShadow call?

Hey guys,

I've run into some problems related to focusing distributed nodes. Specifically:

  • I want a custom-button element to delegate focus to the inner button instance when the custom button is focused.
  • I want a custom-dialog element with <dialog><slot></slot></dialog> to use the normal dialog focus logic (e.g. focusing the distributed node with the autofocus attribute, if one exists).

These behaviors would occur automatically by passing delegatesFocus to the attachShadow call, but Hybrids' render method calls that, and I can't see an easy way to override that.

What are your thoughts?

Property map argument for custom element constructors

Would it be possible to extend the custom element constructor returned by define() as to accept an optional property map with custom values for the component properties?

Suppose I defined an Icon component like:

export default define('custom-icon', {

    name: "",

    render: ({ name }) => {  }

});

It would be very convenient if I could initialise required properties when creating from javascript like:

import Icon from "…/Icon"

new Icon({
    name: 'alert'
})

Instead of:

import Icon from "…/Icon"

const icon=new Icon();

icon.name='alert';

P.S. kudos for the outstanding work :-)

P.P.S besides gitter, do we have a conventional forum for discussing lengthier doubts/proposals? If not, is it acceptable to create question issues here?

Reflecting properties back to attributes

Per Google's Web Fundamentals: Aim to keep primitive data attributes and properties in sync, reflecting from property to attribute, and vice versa.

Is this a thing yet, or no?

My first thought was that I could just implement a custom property descriptor factory that includes this behavior; but I quickly realized that a side-effecting behavior such as this does not belong in a set function.

A helper to render defined element into body on runtime

Hello Dominik Lubański,

I'm learning Hybrids.js and it is cool.
Come from React, Vue, they just need an index.js and include it in index.html,
which is great way to get start!

And sometime, i want to have an element render at runtime and append it to body or app div.
It would be great if just import an utility function from hybrids and it works:

renderTo(
  document.body, // or document.querySelector('#id')
  `<simple-counter count="10"></simple-counter>`
)

Thanks for reading.
NPTien

bundlers : Unexpected character '​'

using webpack 4.27.1

index.js

import {
    html,
    define
} from 'hybrids';

export function increaseCount(host) {
    host.count += 1;
}​
export const SimpleCounter = {
    count: 0,
    render: ({
        count
    }) => html `
      <button onclick="${increaseCount}">
        Count: ${count}
      </button>
    `,
};​
define('simple-counter', SimpleCounter);
const path = require('path');

module.exports = {
    entry: './js/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'bundle.js'
    },
    mode: 'production'
};

Got this error

ash: 87bee4b65e75b1862549
Version: webpack 4.27.1
Time: 268ms
Built at: 2018-12-13 15:14:10
 1 asset
Entrypoint main = bundle.js
[0] ./js/index.js 256 bytes {0} [built] [failed] [1 error]

ERROR in ./js/index.js 10:1
Module parse failed: Unexpected character '​' (10:1)
You may need an appropriate loader to handle this file type.
| export function increaseCount(host) {
|     host.count += 1;
> }​
| export const SimpleCounter = {
|     count: 0,

html: getPropertyName does not convert hyphenated attribute names to camelCased property names

Hi @smalluban, thanks again for creating a great library. Ran across the following bug recently:

The getPropertyName method is passed a string portion of a template literal. This can include bound attribute names that may be hyphenated. Here is the code that passes a template literal piece to getPropertyName:

// html/template.js:324
if (value === PLACEHOLDER) {
  var propertyName = getPropertyName(rawParts[parts.length]);
  parts.push([compileIndex, resolveProperty(name, propertyName, isSVG)]);

However, getPropertyName does not convert hyphenated attribute names to camelCase property names:

// html/template.js:258
// if string = '" start-count="' then the return
// value is 'start-count'; it should be 'startCount'
function getPropertyName(string) {
  return string.replace(/\s*=\s*['"]*$/g, '').split(' ').pop();
}

This causes a bug because the first check resolveProperty makes is to see if the passed propertyName is in the target element. But since the hyphenated property does not exist in the target, it ends up using the default value.

// html/template.js:155
if (!isSVG && propertyName in target) {
  if (target[propertyName] !== value) {
    target[propertyName] = value;

If getPropertyName returned a camelCased name, I think everything would work as expected.

Here is sample code that reproduces the issue.

Hybrids Component within React

Hi! I'm trying to use Web Components as a way to abstract parts of my UI from the parent site.

I'm trying to understand how Hybrids can turn a React component into a custom element, and then have the parent site use that element, especially in development.

image
This is the general architecture of what I'd want my site to look like, and be able to add new (fairly complex) web components into the parent site.

Is Hybrids able to do this? I've just started playing around with Hybrids and saw the react-counter example, but there it was using the custom elements within an index.html file. Can my parent site (React) use those custom elements while they are being developed alongside the parent site?

Really, really cool library btw.

Request for browser property in package.json

Hello
I've just started using this library and I thought i would start by setting up some webpack prep work. I would like to take advantage of the webpack's resolve mainfields option but noticed it doesn't exist for the library in the package.json. Could you please update it? Would really help with bundling dist file of browser rather than using non minified lib/esm version when bundling. cheers.

dispatch: return dispatchEvent result to caller

This is an excellent library -- thank you for writing it. How would you feel about returning the result of dispatch to callers? If the event is cancelable and at least one handler invokes preventDefault(), the return value of dispatchEvent will be false, which could be important to know.

hybrids/src/utils.js

Lines 10 to 11 in 743caeb

export function dispatch(host, eventType, options = {}) {
host.dispatchEvent(new CustomEvent(eventType, { bubbles: false, ...options }));

If you think this is a good idea but don't have time to work on it, let me know and I'll create a PR with the code change, updated README documentation, and unit tests.

property: Immutability and Object.freeze

I'm still feeling hybrids out so I may have missed something really obvious and I apologize in advance if that is the case. Default freezing of objects seems limiting to me. Maybe this is intended as an opinionated part of hybrids or is inherently built in for reasons I don't understand yet. Honestly, I'd rather that preventing mutations was left up to me and I could freeze objects when I declared them instead of it being a default. Looking at the Todo example seems like it's jumping through a lot of hoops to update array values. Anyways, super excited about this framework! It's been great poking at it for a small test project. Thanks!

Using a CSS framework

Hi!

From the docs I understand that to use external CSS content you have to provide it through the style helper when writing a template. It seems to be impossible to share an external stylesheet among custom components, which is kinda problematic when using a CSS framework (like Bootstrap or Bulma).

I've tried to provide the CSS to an app-root component hoping it would pass on the styling to its custom children, but that doesn't seem to be the case. The only way I can think of using a CSS framework now is by importing the stylesheet into every single component, but that's obviously undesirable. Am I missing something? Is there another way?

customize part of rendering with a slot

hi, me again :)

I tried to find something in the docs and the exising issues before posting here but didn't find anything, so here we go:

I'm trying to use <slot> to let the user of my web component customize how an item of a list should be rendered.

For now I'm trying something like:

<fulltext-search index-url="https://localhost/docs/search-index.json">
    <template slot="result-item">
        <h1>custom result item ${result.ref}</h1>
        <a href="https://localhost/documentation/docs/${result.ref}">${result.ref}</a>
    </template>
</fulltext-search>

Note: using <template> here is a bad idea as it won't be interpreted (tried with <div> as well, no success, the problem is elsewhere).

The web component defines a <slot name="result-item"> in the loop, which is a bad idea as well, since many slots have the same name.

  render: ({ query, results }) => html`
    <input placeholder="search" type="search" oninput="${(host, event) => host.query = event.target.value}" />
    <ul>${html.resolve(
      results.then(
        r => html`${r.map(result => html`<li>
            <slot name="result-item">
               ${result.ref}
            </slot>
        </li>`)}`
      ).catch(e => html`${e}`),
      html`…`
    )}</ul>

Any idea how I could do that ?

Thanks :)

Testing

Okay, since hybrids is functional, testing methods are quite easy, but I wanted to know if we can make integration ro e2e tests.
e2e tests are quite hard, since e2e testing libraries - like cypress - can't access shadow dom, so maybe document about testing with it would be nice

Is it possible to use hybrids without a build process ?

Could you please provide a hint or two to write components without Webpack to get going?

It would seem a nice workflow to use a component by just importing the pre-built js and import one or two components on the page and leverage caching for pages primarily consisting of the occasional component. ES6+ only is fine.

I read a couple of writeup for Vue, but I´m not skilled enough to translate into something that would apply to hybrids:
https://markus.oberlehner.net/blog/goodbye-webpack-building-vue-applications-without-webpack/
https://medium.com/@steveolensky/create-a-spa-vuejs-application-without-node-webpack-or-any-other-build-process-using-vue-router-b9bf8e36e958

I´m not sure if this is a reasonable way to go about it by referencing window.hybrids

<html>
    <head>
        <title>Test 2</title>
    </head>
    <body>
        <script src="https://unpkg.com/[email protected]/dist/hybrids.js"></script>
        <p>Test this</p> 
        <simple-counter></simple-counter>
        <script type="module">
export function increaseCount(host) {
  host.count += 1;
}

export const SimpleCounter = {
  count: 0,
  render: ({ count }) => window.hybrids.html`
    <button onclick="${increaseCount}">
      Count: ${count}
    </button>
  `,
};    

window.hybrids.define('simple-counter', SimpleCounter);
        </script>
    </body>
</html>

Regards,

Running DOM updates after rendering

Hi!
Apologies up-front if this question is already answered in the documentation or in another issue, but I couldn't find a direct answer to my problem.
Imagine I have <log-transcript> - a scrollable component that is connected to an array of log lines from a redux state, and renders the log whenever a line is added, something like this:

export default {
    transcript: connect(store, (state) => state.transcript),
    render: ({transcript}) => { 
       return html`
        <style>
            #transcript-container {
                overflow: scroll;
            }
        </style>
        <div id="transcript-container">
            ${transcript.map(( line ) => html
                `<div class="transcript-line">${line.text}</div>
            `)}
        </div>
     `
   }
}

Now I would like to have the element automatically scroll down to the latest line upon update.
This is done using:

 container.scrollTop = container.scrollHeight;

But it must be called after the container has the updated scrollHeight. Where would the appropriate location for this code? So far I could only work around this by calling a function from render() and using setTimeout(0).

Thanks!

/Avner

PostCSS support?

It’d be great to have a hook, or ability to run a preprocessor in the <style> template. This would basically allow nested declarations, CSS variables, and other polyfills/plugins PostCSS affords.

Because PostCSS spits out standards-compliant CSS, it could just spit out the plain-CSS result back to <style> and let Hybrids do its thing normally. So long as it happened as the first step.

Would it be possible to allow for a transform function to happen before shadycss reads the <style> template?

Sample app error using Parcel.js

I've npm install hybrids and copied the files from the simple-counter example app.

When I run: parcel index.html I get:

utils.js:50 Uncaught TypeError: Cannot use 'in' operator to search for 'ActiveXObject' in undefined
    at Object.parcelRequire.node_modules/hybrids/esm/utils.js (utils.js:50)
    at newRequire (brutal.e31bb0bc.js:49)
    at localRequire (brutal.e31bb0bc.js:55)
    at Object.parcelRequire.node_modules/hybrids/esm/property.js../utils (property.js:1)
    at newRequire (brutal.e31bb0bc.js:49)
    at localRequire (brutal.e31bb0bc.js:55)
    at Object.parcelRequire.node_modules/hybrids/esm/define.js../property (define.js:1)
    at newRequire (brutal.e31bb0bc.js:49)
    at localRequire (brutal.e31bb0bc.js:55)
    at Object.parcelRequire.node_modules/hybrids/esm/index.js../define (index.js:1)

because global is undefined. If I edit utils.js and change global to window the app runs correctly, but this is of course a hack.

Parcel.js home page.

Dependencies page feedback

When using the .define helper method, it seems as if it automatically translates from UiHeader to ui-header when creating the definition, but it isn't explicitly documented that it does the translation for you based on the use of camel case.

At least in my case, I was confused upon reading the documentation, but I figured it out when using the method. It might be helpful to document that functionality, though.

Using external css libraries

I'm trying to use bootstrap tags inside hybrids' components and it's not taking any effect. How can I make web components get bootstrap styles?

Repo missing v2.0.0 tag/release

Ran into some inconsistencies using this tool until I realized the repo's listed tags were out of sync with NPM for the v2.0.0 release.

Would clear up potential confusion if the v2.0.0 tag/release was in the repo as well.

Hooks?

Hello.

Any thoughts on how we might get a useState like capability in Hybrids?

Or other capabilities in React Hooks?

I feel like Hybrids has a more explicit idea of state- that the component itself keeps getting its properties passed to it, via the arguments each render() call gets. This may perhaps make hooks unnecessary, but I'm not sure. What are your thoughts? Perhaps some additional documentation could be added to help onboard users used to React Hooks, as they come to Hybrids' functional component model?

Styling a nested React component within a Hybrids component

Hi!
I am just beginning with Hybrids and so far enjoying it very much, but I ran across an issue regarding the integration with React.
I am trying to use a React component inside my Hybrids layout. The component loads with the reactify method as in the react-counter example. However, I'm not sure what would be the best approach for styling the component. Let's say I get a CSS along with the 3rd party component that I can load or inject anywhere - I couldn't find how to inject this style to the component created by reactifiy. My best bet was to wrap the 'reactified'' component in another Hybrids component that also includes the style, and render the React component with shadowRoot: false. However, this for some reason breaks the handling of events in the React component. I was able to recreate the event issue in a react-counter example fork.
Could you tip me on the best direction to proceed?
Thank you for the work on this project!
/Avner

render: styling concern

Hi, how do you suppose to style the host element, the slotted elements and host-context based elements? Also there is a way to add component scoped global style without binding it to an element (something like .class:not(div) ~ p[dir="rtl" i]:nth-of-type(2) {})?

Rendering WC into VueJS

Love your library btw! keep up the good work!

My Problem with Hybrids

This might not be an issue but a bug from my side, but your help is greatly appreciated. I'm trying to wrap some react components into web components to offer them to all non-react developers.
what the code does is basically grab all react components and create a web component wrapper for each. it then formats the object and passes the formatted object to your fine define method.

import {define, render} from 'hybrids';
import * as Components from '@momentum-ui/react';
import React from 'react';
import ReactDOM from 'react-dom';

// Grab all of the momentum-ui react components
const webComponents = Object.keys(Components).map(key => {
  // Convert the PascalCase string with lowercase string plus dashes in between
  const name = `web-comp${key.replace(/[A-Z]/g, m => "-" + m.toLowerCase())}`;
  const component = {
      render: render(() => {
        // Grab the react component whenever being invoked
        const Component = Components[key];
    
        return (host, target) => {
          // Render the component with the given properties
          ReactDOM.render(<Component {...host} />, target)
        }
      },  { shadowRoot: false }) // No to Shadow DOM
    };

  return {name, component};
});

const formattedWebComponents = webComponents.reduce((result, item) => {
  const component = Object.keys(item)[1];

  // web-comp-avatar: Avatar Constructor
  result[Object.values(item)[0]] = item[component];
  return result;
}, {})

define(formattedWebComponents);

This solution works fine in Angular. However, Vue application does not pass the properties accordingly. they are all undefined.

my Vue.js application:

import Vue from 'vue';
import './momentum-ui.scss';
import '../../../web-components';

Vue.component('app', {
  data: () => {
    return {
      src: 'https://8e325148c33e40909d40-0b990d1d119de8e505829619be483465.ssl.cf1.rackcdn.com/V1~47c32d0b-0444-460d-8bce-2265b501aac5~bfc8719afb284d998b25362fbffc7d43~1600',
      type: 'active'
    }
  },
  template: `
    <div className='parent-container'>
      <web-comp-avatar 
        :src="src"
        :type="type"
      /> 
    </div>`
})


new Vue({ 
  el: '#components-demo'
})

connect: addEventListener on components

I wanted to know if there is a way of adding a eventListener to the component that listen do "document". I've tried doing something that looked like redux connect function but I wasn't able to make it work.
Could you provide some example? Or at least put it on the docs,

Use lit-html internally

Instead of having your own html template literal, maybe it would be better if hybrids used a famous lib for it. It would help people when looking for documentation about how to write it.
Lit-html is backed by polymer as well, and its html and render api are already stable.

dispatch: modify dispatch to accept Event object instead of eventType and options

Hello again.

Any chance you can modify dispatch to accept an Event object directly? The idea is to dispatch that Event if provided, or else fall back to the current functionality of creating a new CustomEvent for the developer.

I'd like to create event "envelopes" that team members can use to provide variable information in an expected format to ancestor event handlers.

For example, here's what I'd like to do:

import { actionCreator, actionEvent } from 'shared/actions';

function buttonClicked(host) {
    const event = actionEvent(actionCreator(/* possible data here */));
    dispatch(host, event);
}

const MyComponent = {
    render: () => html`
        <button onclick="${buttonClicked}">click me</button>
    `
}

The alternative is calling dispatchEvent manually, which might confuse some developers as it requires writing different code for what is fundamentally the same concept:

function buttonClicked(host) {
    const event = actionEvent(actionCreator(/* possible data here */));
    host.dispatchEvent(event); // use built-in EventTarget method
    // but this inconsistency might confuse other developers
}

Or, even worse:

function buttonClicked(host) {
    const action = actionCreator(/* possible data here */);
    dispatch(host, 'action-event', {
        bubbles: true,
        composed: true,
        cancelable: true,
        detail: action
    });
    // has to be written every time
}

I know it's a minor request, but it's one that could provide some nice conformity to end users.

Regarding limitations of expressions in styles

Reading the styling documentation - https://github.com/hybridsjs/hybrids/blob/master/docs/template-engine/styling.md - it says that due to how ShadyCSS works, expressions do not work for browsers that do not support Shadow DOM natively.

I think this is a big limitation to adoption of hybrids because css-in-js is growing ever popular.

I gave it a try and as expected it did not work when running Edge.

Then I kept on reading and saw the part about the style helper and wondered if that doesn't solve the problem anyway? Since it takes css as a string, that string does not have to come from an external file.

So I gave this a try,

const fontSize = {
  normal: "1rem",
};

const style = `
    h1 {
      font-size: ${fontSize.normal};
    }
`;

const App = {
  render: () =>
    html`
      <h1>Hello World</h1>
    `.style(style),
};

And to my amazement this works in Edge! The style is properly scoped and the expression properly evaluated.

So styles with expressions can work with ShadyCSS as well!

You could also take advantage of state properties as well to change style based on them.

const fontSize = {
  normal: "1rem",
};

const style = isRed => `
    h1 {
      color: ${isRed ? "red" : "blue"};
      font-size: ${fontSize.normal};
    }
`;

const App = {
  isRed: true,
  render: ({ isRed }) =>
    html`
      <h1>Hello World</h1>
    `.style(style(isRed)),
};

I don't see any immediate downsides to doing this but perhaps you do?

html|promise: Rendering property after http request

I have a property that inside it's connect, I make a http request, but it sometimes render, and sometimes don't. I have to keep refreshing the page until one time the component renders the api response.

I'm doing like this:

import { html } from 'hybrids';
import { getOngs } from '../services/ongsService';
import materializeStyle from '../styles';

const ongsProperty = ({
  get: (host, lastValue) => lastValue || [],
  set: (host, newValue) => newValue,
  connect: async (host, key, invalidate) => {
    host.ongs = await getOngs();
    return () => {};
  },
});

const ongsListRender = ({ ongs }) => html`
  ${materializeStyle}
  <h1>Help My.ONG</h1>
  ${JSON.stringify(ongs)}
  <ul class="collapsible">
  ${ongs.map(ong => html`
    <li>
      <div class="collapsible-header">${ong.name} - ${ong.taskTitle}</div>
      <div class="collapsible-body"><span>Lorem ipsum</span></div>
    </li>
  `)}
  </ul>
`;


const ongsList = {
  ongs: ongsProperty,
  render: ongsListRender,
};

export default ongsList;

I've made it work by putting a console.log(await getOngs()) above host.ongs = await getOngs();, but I guess this is a wrong thing to do.

Make Hybrids.js more beginner-friendly

Hi Dominik Lubański

React, Vue are very beginner-friendly.
Especially for someone like me who want to see the results fast by
clone a repo, type yarn && yarn dev and hit enter,
edit code and see changes immediately in browser.

That is a great selling point. I want to clone a repo and start from there
instead of configing webpack or parcel.

Have a create-hybrids-app with some templates is great!

Another thing that i want to request is that include all the live examples in /example this repo or another repo examples in hybridsjs org.
Looking at VSCode is better than looking at browser in working time. ;D

Thanks for reading.

NPTien

property: React not re-rendering when i change web component attribute

I created a basic web component based on react. I do this:

`

    ....
  css: '',
    render: ({chain, hotel, arrival, departure, css}) => {
        console.log(chain);

        return reactify(
            <div>
                <link rel="stylesheet" href={css} />
                <ProductListWrapper chain={chain} hotel={hotel} arrival={arrival} departure={departure} />
            </div>
        )
    },

`

and when i change a web component attribute manually in dev tools or via:

let myElement = document.getElementsByTagName('kutasiki')[0]
myElement.setAttribute('chain', 22)
myElement.render()

i doesnt rerender react component to consume up to date attributes. I'm missing something here?

Hybrids SSR

I was studing SSR with WebComponents, and it's quite easy with Web Components, i just need to use new Component() with my component class with skatejs library and it's done! I'd like to know if hybrids' define method returns a class so I can do SSR with Hybrids.

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.