ryansolid / component-register Goto Github PK
View Code? Open in Web Editor NEWA simple library wrapper for Web Components
License: MIT License
A simple library wrapper for Web Components
License: MIT License
Hi There,
In case a prop should be reflected and has a string value,
JSON.stringify produces quoted result, which end quoted in the attribute value.
It would be better, stringigfy is not used for strings.
let reflect = JSON.stringify(value);
I know, the behaviour is harmless for parsing, but it kinda breaks with CSS selectors
Standard web component has 3 key lifecycle point: create(constructor), connected, disconnected. This is because an element may be remove from dom and added back again and again. With these hooks, we could create something in constructure but reuse them from time to time.
But lifecycles defined by this repo are only create
and release
, which means we have to recreate all thing after reconnecting.
Am I missing something? Or how could we handle this?
Polyfill not properly parsing :host styling.
Input:
:host(.light)
::slotted(a:active)
color:#1a1a1a
Output:
:host(.light) example_component slot > a:active{color:#1a1a1a;}
Hi there,
I have a situation where I have defined a property with a default/initial value,
which is a "thrithy" value
Now the consumer adds/defines the attribute and provides a "falsy" value for this,
and after a while, the attribute gets removed again.
I know this is nothing that should happen, but in our demo system, it is the case.
Now according to this statement:
if (name in propDefinition) {
if (newVal == null && !this[name]) return;
this[name] = propDefinition[name].parse ? parseAttributeValue(newVal) : newVal;
}
Processing of the attribute change stops du to the fact the value is falsy.
But I need it to be the default again.
I have tried to use attribute changed callback, to add my own logic, but unfortunately
this is not called, since it is only called after the attribute has been successfully changed.
Would it be possible to either:
In general, it would be very nice to provide custom value parser to the prop by config.
I don't mind to make a PR if you agree with this request.
Thanks in Advance ๐
Does this library support SSR?
I'm kinda working on a new approach to micro frobtends
I want to avoid webpack and module federation
I'll probably use vanilla js with jsdoc type defs
The goal is to create a sort of iframe that isn't: I'm thinking of calling it "FakeFrame" it just fetches the html for another app, and injects it into this shadow dom container.
It could use solid but probably shouldn't because it's not necessary.
When rendering server side, it would make the same request for an apps html. If that app gave us server side rendered html, all the better, if not, the scripts will render client side, as that app expects.
Hello Ryan!
I'm making a web component that displays information about a Discord ID, meaning someone could use <discord-user user-id="210246661446959104" />
and it would display its username and more information. Unfortunately, due to this line ( https://github.com/ryansolid/component-register/blob/master/src/utils.ts#L118 ) the Discord ID gets converted to a number which breaks it because that converts it to 210246661446959100
.
In my humble opinion, automatic parsing should not be done on incoming argument values, as is made evident here.
Hi, is it possible to expose custom methods on the final web component object? I would need a way to expose some api from the component (think of a player play()
, pause()
).
I have built a generic wrapper to create custom elements.
And I would like to reuse PropDefinition<T>
type in my code.
At the moment I do this ugly stuff in order to acquire the type:
... PropsDefinitionInput<{ [PP in P]: T[PP] | undefined | null }>[P];
Thanks in advance ๐
How to create a custom elements without shadow dom? The readme didn't talk about that. After searching I found there is a noShadowDOM
function and I tried to call it in the hoc, it seems take effect but I am not sure if it will affect other creations which didn't call it (which should have the shadow dom).
I've been working on a vanilla js implementation of a web component for a shopify store. Weirdly enough... only when the web component is nested within an anchor tag does the following functionality error.
Is there something I'm doing wrong here?
import {
createEffect,
createMemo,
createRoot,
createSignal,
onCleanup,
on,
For,
Show,
} from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
import { insert } from 'https://cdn.jsdelivr.net/npm/[email protected]/web/+esm';
import html from 'https://cdn.jsdelivr.net/npm/[email protected]/html/+esm';
import {
register,
createContext,
withProvider,
withConsumer,
compose,
} from 'https://cdn.jsdelivr.net/npm/[email protected]/+esm';
// Utility custom element functions
function getContext(element) {
const elementContextSymbol = Object.getOwnPropertySymbols(element).find((s) => s.description === 'element-context');
const contextSymbol = Object.getOwnPropertySymbols(element[elementContextSymbol]).find(
(s) => s.description === 'context'
);
return element[elementContextSymbol][contextSymbol];
}
function createProps(raw) {
const keys = Object.keys(raw);
const props = {};
for (let i = 0; i < keys.length; i++) {
const [get, set] = createSignal(raw[keys[i]]);
Object.defineProperty(props, keys[i], {
get() {
return get();
},
set(v) {
set(() => v);
},
});
}
return props;
}
function lookupContext(el) {
if (el.assignedSlot && el.assignedSlot._$owner) return el.assignedSlot._$owner;
let next = el.parentNode;
while (next && !next._$owner && !(next.assignedSlot && next.assignedSlot._$owner)) next = next.parentNode;
return next && next.assignedSlot ? next.assignedSlot._$owner : el._$owner;
}
function withSolid(ComponentType) {
return (rawProps, options) => {
const { element } = options;
return createRoot((dispose) => {
const props = createProps(rawProps);
element.addPropertyChangedCallback((key, val) => (props[key] = val));
element.addReleaseCallback(() => {
element.renderRoot.textContent = '';
dispose();
});
const comp = ComponentType(props, options);
return insert(element.renderRoot, comp);
}, lookupContext(element));
};
}
function withNoShadowDOM(ComponentType = (props, options) => {}) {
return (props, options) => {
const { element } = options;
element.renderRoot = element;
return ComponentType(props, options);
};
}
const customShadowlessElement = (tagName, props = {}, Component = (props, options) => {}, ...rest) =>
compose(register(tagName, props), withNoShadowDOM, withSolid, ...rest)(Component);
const ItemContext = createContext((index = 0) => {
const [idx, setIdx] = createSignal(index);
const item = createMemo(() => Shopify.StorefrontCart.cart().items[idx()]);
return [item, setIdx];
});
function CartItemContext(props, { element }) {
const [item, setIdx] = getContext(element);
createEffect(on(item, (item) => console.log(item, 'TESTING')));
createEffect(
on(
() => props.position,
(position) => setIdx(position)
)
);
}
function CartItems(props, { element }) {
const itemTMPL = element.querySelector('template');
if (!itemTMPL) return;
return html`
<${Show} when=${() => Shopify.StorefrontCart.cart() && Shopify.StorefrontCart.cart().items.length > 0}>
<${For} each=${() => Shopify.StorefrontCart.cart().items}>
${(_, idx) => html` <cart-item-context position=${() => idx()}
>${() => itemTMPL.content.cloneNode(true)}</cart-item-context
>`}
<//>
<//>
`;
}
function CartItem(props, { element, itemContext }) {
console.log(Object.entries(element), 'TESTING');
const [item] = itemContext;
const value = createMemo(() => {
const i = item();
console.log(i);
const keys = props.propertyName.split('.').filter((key) => key.length > 0);
const v = keys.reduce((acc, key) => acc[key], i);
switch (props.format) {
case 'currency':
return Shopify.formatMoney(v);
case 'number':
return v;
case 'link':
const tmpl = element.querySelector('template');
return html`<a
class=${element.getAttribute('class') || ''}
style=${element.getAttribute('style') || ''}
href=${v}
>${tmpl.content.cloneNode(true)}</a
>`;
default:
return v;
}
});
return html` <${Show} when=${value}> ${value} <//> `;
}
customShadowlessElement('cart-items', {}, CartItems);
customShadowlessElement(
'cart-item',
{ propertyName: '', format: 'none' },
CartItem,
withConsumer(ItemContext, 'itemContext')
);
customShadowlessElement('cart-item-context', { position: 0 }, CartItemContext, withProvider(ItemContext));
<cart-items>
<template>
<div>
<cart-item property-name="url" format="link">
<cart-item property-name="title"></cart-item>
</cart-item>
<a href="#">
<cart-item property-name="title"></cart-item>
</a>
<cart-item property-name="quantity"></cart-item>
</div>
</template>
</cart-items>
<cart-items>
<template>
<div>
<cart-item property-name="url" format="link">
<cart-item property-name="title"></cart-item>
</cart-item>
<a href="#">
<cart-item property-name="title"></cart-item>
</a>
<cart-item property-name="quantity"></cart-item>
</div>
</template>
<cart-item-context>
<div>
<!-- This works and renders an a tag--->
<cart-item property-name="url" format="link">
<a href="/products/testing" class="" style="">
<!-- Error creating component CartItem: TypeError: itemContext is not iterable --->
<cart-item property-name="title"></cart-item>
</a>
</cart-item>
<a href="#">
<!-- Error creating component CartItem: TypeError: itemContext is not iterable --->
<cart-item property-name="title">Testing</cart-item>
</a>
<!-- This works and renders the quantity --->
<cart-item property-name="quantity">1</cart-item>
</div>
</cart-item-context>
</cart-items>
Any help here would be greatly appreciated! Thanks ahead of time!
I'm new to custom elements but, from what I've read, it would be within this wrapper that the formAssociated setting would need to be made.
Are there plans to update this library to support that?
Regards
John
I tried to use solid-element to setup a web component library project, but for some reason when trying to generate types during build, it throws error
../../node_modules/component-register/types/element.d.ts:185:26 - error TS2304: Cannot find name 'DocumentAndElementEventHandlers'.
Hi there,
I tried to figure out how the notify
option work.
Unfortunately, I did not find any references to it in the code.
is it missing?
Thanks ๐
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.