~repos /atoms-element
git clone
https://pyrossh.dev/repos/atoms-element.git
A simple web component library for defining your custom elements. It works on both client and server.
file:
index.js
import { html, render as litRender, directive, NodePart, isPrimitive } from './lit-html.js';
const isBrowser = typeof window !== 'undefined';export { html, isBrowser };
const lastAttributeNameRegex = /([ \x09\x0a\x0c\x0d])([^\0-\x1F\x7F-\x9F "'>=/]+)([ \x09\x0a\x0c\x0d]*=[ \x09\x0a\x0c\x0d]*(?:[^ \x09\x0a\x0c\x0d"'`<>=]*|"[^"]*|'[^']*))$/;const tagRE = /<[a-zA-Z0-9\-\!\/](?:"[^"]*"|'[^']*'|[^'">])*>/g;const whitespaceRE = /^\s*$/;const attrRE = /\s([^'"/\s><]+?)[\s/>]|([^\s=]+)=\s?(".*?"|'.*?')/g;const voidElements = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'];const STRIP_COMMENTS = /(\/\/.*$)|(\/\*[\s\S]*?\*\/)|(\s*=[^,\)]*(('(?:\\'|[^'\r\n])*')|("(?:\\"|[^"\r\n])*"))|(\s*=[^,\)]*))/gm;const ARGUMENT_NAMES = /([^\s,]+)/g;
const parseFuncParams = (func) => { const fnStr = func.toString().replace(STRIP_COMMENTS, ''); const result = fnStr.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')')).match(ARGUMENT_NAMES); return (result || []).filter((it) => it !== '{' && it !== '}');};
const parseTag = (tag) => { const res = { type: 'tag', name: '', voidElement: false, attrs: {}, children: [], };
const tagMatch = tag.match(/<\/?([^\s]+?)[/\s>]/); if (tagMatch) { res.name = tagMatch[1]; if (voidElements.includes(tagMatch[1]) || tag.charAt(tag.length - 2) === '/') { res.voidElement = true; }
// handle comment tag if (res.name.startsWith('!--')) { const endIndex = tag.indexOf('-->'); return { type: 'comment', comment: endIndex !== -1 ? tag.slice(4, endIndex) : '', }; } }
const reg = new RegExp(attrRE); let result = null; for (;;) { result = reg.exec(tag);
if (result === null) { break; }
if (!result[0].trim()) { continue; }
if (result[1]) { const attr = result[1].trim(); let arr = [attr, ''];
if (attr.indexOf('=') > -1) { arr = attr.split('='); }
res.attrs[arr[0]] = arr[1]; reg.lastIndex--; } else if (result[2]) { res.attrs[result[2]] = result[3].trim().substring(1, result[3].length - 1); } }
return res;};const parseHtml = (html) => { const result = []; const arr = []; let current; let level = -1;
// handle text at top level if (html.indexOf('<') !== 0) { var end = html.indexOf('<'); result.push({ type: 'text', content: end === -1 ? html : html.substring(0, end), }); }
html.replace(tagRE, function (tag, index) { const isOpen = tag.charAt(1) !== '/'; const isComment = tag.startsWith('<!--'); const start = index + tag.length; const nextChar = html.charAt(start); let parent;
if (isComment) { const comment = parseTag(tag);
// if we're at root, push new base node if (level < 0) { result.push(comment); return result; } parent = arr[level]; parent.children.push(comment); return result; }
if (isOpen) { level++;
current = parseTag(tag);
if (!current.voidElement && nextChar && nextChar !== '<') { current.children.push({ type: 'text', content: html.slice(start, html.indexOf('<', start)), }); }
// if we're at root, push new base node if (level === 0) { result.push(current); }
parent = arr[level - 1];
if (parent) { parent.children.push(current); }
arr[level] = current; }
if (!isOpen || current.voidElement) { if (level > -1 && (current.voidElement || current.name === tag.slice(2, -1))) { level--; // move current up a level to match the end tag current = level === -1 ? result : arr[level]; } if (nextChar !== '<' && nextChar) { // trailing text node // if we're at the root, push a base text node. otherwise add as // a child to the current node. parent = level === -1 ? result : arr[level].children;
// calculate correct end of the content slice in case there's // no tag after the text node. const end = html.indexOf('<', start); let content = html.slice(start, end === -1 ? undefined : end); // if a node is nothing but whitespace, collapse it as the spec states: // https://www.w3.org/TR/html4/struct/text.html#h-9.1 if (whitespaceRE.test(content)) { content = ' '; } // don't add whitespace-only text nodes if they would be trailing text nodes // or if they would be leading whitespace-only text nodes: // * end > -1 indicates this is not a trailing text node // * leading node is when level is -1 and parent has length 0 if ((end > -1 && level + parent.length >= 0) || content !== ' ') { parent.push({ type: 'text', content: content, }); } } } });
return result;};
const stringifyAttrs = (attrs) => { const buff = []; for (let key in attrs) { buff.push(key + '="' + attrs[key] + '"'); } if (!buff.length) { return ''; } return ' ' + buff.join(' ');};
const stringifyHtml = (buff, doc) => { switch (doc.type) { case 'text': return buff + doc.content; case 'tag': buff += '<' + doc.name + (doc.attrs ? stringifyAttrs(doc.attrs) : '') + (doc.voidElement ? '/>' : '>'); if (doc.voidElement) { return buff; } return buff + doc.children.reduce(stringifyHtml, '') + '</' + doc.name + '>'; case 'comment': buff += '<!--' + doc.comment + '-->'; return buff; }};
const hydrate = (node) => { const Clazz = getElement(node.name); if (Clazz) { const newAttrs = {}; Object.keys(node.attrs).forEach((key) => { const newValue = node.attrs[key]; newAttrs[key] = newValue && newValue.startsWith(`{`) ? JSON.parse(newValue.replace(/'/g, `"`)) : newValue; }); const instance = new Clazz(newAttrs); const res = instance.render(); node.children = parseHtml(res); } if (node.children) { for (const child of node.children) { hydrate(child); } }};
const wrapAttribute = (attrName, suffix, text, v) => { let buffer = text; const hasQuote = suffix && suffix.includes(`="`); if (attrName && !hasQuote) { buffer += `"`; } buffer += v; if (attrName && !hasQuote) { buffer += `"`; } return buffer;};
export const renderHtml = isBrowser ? litRender : (template) => { let js = ''; template.strings.forEach((text, i) => { const value = template.values[i]; const type = typeof value; let attrName, suffix; const matchName = lastAttributeNameRegex.exec(text); if (matchName) { attrName = matchName[2]; suffix = matchName[3]; } if (value === null || !(type === 'object' || type === 'function' || type === 'undefined')) { js += wrapAttribute(attrName, suffix, text, type !== 'string' ? String(value) : value); } else if (Array.isArray(value) && value.find((item) => item && item.strings && item.type === 'html')) { js += text; value.forEach((v) => { js += renderHtml(v); }); } else if (type === 'object') { // TemplateResult if (value.strings && value.type === 'html') { js += text; js += renderHtml(value); } else { js += wrapAttribute(attrName, suffix, text, JSON.stringify(value).replace(/"/g, `'`)); } } else if (type == 'function') { if (attrName) { js += text.replace(' ' + attrName + '=', ''); } else { // js += text; // js += value(); } } else if (type !== 'undefined') { js += text; js += value.toString(); } else { js += text; // console.log('value', value); } }); const nodes = parseHtml(js); for (const node of nodes) { hydrate(node); } const html = nodes.reduce((acc, node) => { return acc + stringifyHtml('', node); }, ''); return html; };
const hyphenate = (s) => s.replace(/[A-Z]|^ms/g, '-$&').toLowerCase();const percent = (v) => (v * 100).toFixed(2) + '%';const createStyle = (...kvs) => { const style = {}; for (let i = 0; i < kvs.length; i += 2) { style[hyphenate(kvs[i])] = kvs[i + 1]; } return style;};
const mapApply = (obj) => Object.keys(obj.keys).reduce((acc, key) => { Object.keys(obj.values).map((vkey) => { const suffix = vkey ? '-' + vkey : ''; const className = `${key}${suffix}`; if (Array.isArray(obj.keys[key])) { const args = []; obj.keys[key].forEach((kk) => { args.push(kk, obj.values[vkey]); }); acc[className] = createStyle(...args); } else { acc[className] = createStyle(obj.keys[key], obj.values[vkey]); } }); return acc; }, {});
export const css = (obj, isChild = false, indent = '') => { const cssText = Object.keys(obj).reduce((acc, key) => { const value = obj[key]; acc += !isChild ? `${key} {\n` : ''; if (typeof value === 'object') { acc += '\n' + css(value, true, indent + ' '); } else { acc += ' ' + indent + hyphenate(key) + ': ' + value + ';\n'; } acc += !isChild ? `\n}\n` : ''; return acc; }, ''); return cssText;};
const extractClasses = (html) => { let str = ''; const matches = html.match(/class=(?:["']\W+\s*(?:\w+)\()?["']([^'"]+)['"]/gim); if (matches) { matches.forEach((matched, i) => { str += matched.replace('class="', '').replace('"', '') + (i === matches.length - 1 ? '' : ' '); }); } return str;};
const getClassList = (template) => { // need to have this incase of shadowDom // const classes = template.strings.reduce((acc, item) => acc + extractClasses(item), '').split(' '); const classes = []; template.values.forEach((item) => { if (typeof item === 'string') { const list = item.split(' '); return classes.push(...list.filter((cls) => classLookup[cls])); } return false; }); return classes;};
export const compileTw = (classList) => { let styleSheet = ``; classList.forEach((cls) => { const item = classLookup[cls]; if (item) { const className = cls.replace(`/`, `\\/`); styleSheet += ` .${className} { ${Object.keys(item) .map((key) => `${key}: ${item[key]};`) .join('\n')} } `; } }); return styleSheet;};
const colors = { keys: { bg: 'backgroundColor', text: 'color', divide: 'borderColor', border: 'borderColor', ring: '--tw-ring-color', 'border-l': 'borderLeftColor', 'border-r': 'borderRightColor', 'border-t': 'borderTopColor', 'border-b': 'borderBottomColor', }, values: { transparent: 'transparent', current: 'currentColor', black: 'rgba(0, 0, 0, 1)', white: 'rgba(255, 255, 255, 1)', 'gray-50': 'rgba(249, 250, 251, 1)', 'gray-100': 'rgba(243, 244, 246, 1)', 'gray-200': 'rgba(229, 231, 235, 1)', 'gray-300': 'rgba(209, 213, 219, 1)', 'gray-400': 'rgba(156, 163, 175, 1)', 'gray-500': 'rgba(107, 114, 128, 1)', 'gray-600': 'rgba(75, 85, 99, 1)', 'gray-700': 'rgba(55, 65, 81, 1)', 'gray-800': 'rgba(31, 41, 55, 1)', 'gray-900': 'rgba(17, 24, 39, 1)', 'red-50': 'rgba(254, 242, 242, 1)', 'red-100': 'rgba(254, 226, 226, 1)', 'red-200': 'rgba(254, 202, 202, 1)', 'red-300': 'rgba(252, 165, 165, 1)', 'red-400': 'rgba(248, 113, 113, 1)', 'red-500': 'rgba(239, 68, 68, 1)', 'red-600': 'rgba(220, 38, 38, 1)', 'red-700': 'rgba(185, 28, 28, 1)', 'red-800': 'rgba(153, 27, 27, 1)', 'red-900': 'rgba(127, 29, 29, 1)', 'yellow-50': 'rgba(255, 251, 235, 1)', 'yellow-100': 'rgba(254, 243, 199, 1)', 'yellow-200': 'rgba(253, 230, 138, 1)', 'yellow-300': 'rgba(252, 211, 77, 1)', 'yellow-400': 'rgba(251, 191, 36, 1)', 'yellow-500': 'rgba(245, 158, 11, 1)', 'yellow-600': 'rgba(217, 119, 6, 1)', 'yellow-700': 'rgba(180, 83, 9, 1)', 'yellow-800': 'rgba(146, 64, 14, 1)', 'yellow-900': 'rgba(120, 53, 15, 1)', 'green-50': 'rgba(236, 253, 245, 1)', 'green-100': 'rgba(209, 250, 229, 1)', 'green-200': 'rgba(167, 243, 208, 1)', 'green-300': 'rgba(110, 231, 183, 1)', 'green-400': 'rgba(52, 211, 153, 1)', 'green-500': 'rgba(16, 185, 129, 1)', 'green-600': 'rgba(5, 150, 105, 1)', 'green-700': 'rgba(4, 120, 87, 1)', 'green-800': 'rgba(6, 95, 70, 1)', 'green-900': 'rgba(6, 78, 59, 1)', 'blue-50': 'rgba(239, 246, 255, 1)', 'blue-100': 'rgba(219, 234, 254, 1)', 'blue-200': 'rgba(191, 219, 254, 1)', 'blue-300': 'rgba(147, 197, 253, 1)', 'blue-400': 'rgba(96, 165, 250, 1)', 'blue-500': 'rgba(59, 130, 246, 1)', 'blue-600': 'rgba(37, 99, 235, 1)', 'blue-700': 'rgba(29, 78, 216, 1)', 'blue-800': 'rgba(30, 64, 175, 1)', 'blue-900': 'rgba(30, 58, 138, 1)', 'indigo-50': 'rgba(238, 242, 255, 1)', 'indigo-100': 'rgba(224, 231, 255, 1)', 'indigo-200': 'rgba(199, 210, 254, 1)', 'indigo-300': 'rgba(165, 180, 252, 1)', 'indigo-400': 'rgba(129, 140, 248, 1)', 'indigo-500': 'rgba(99, 102, 241, 1)', 'indigo-600': 'rgba(79, 70, 229, 1)', 'indigo-700': 'rgba(67, 56, 202, 1)', 'indigo-800': 'rgba(55, 48, 163, 1)', 'indigo-900': 'rgba(49, 46, 129, 1)', 'purple-50': 'rgba(245, 243, 255, 1)', 'purple-100': 'rgba(237, 233, 254, 1)', 'purple-200': 'rgba(221, 214, 254, 1)', 'purple-300': 'rgba(196, 181, 253, 1)', 'purple-400': 'rgba(167, 139, 250, 1)', 'purple-500': 'rgba(139, 92, 246, 1)', 'purple-600': 'rgba(124, 58, 237, 1)', 'purple-700': 'rgba(109, 40, 217, 1)', 'purple-800': 'rgba(91, 33, 182, 1)', 'purple-900': 'rgba(76, 29, 149, 1)', 'pink-50': 'rgba(253, 242, 248, 1)', 'pink-100': 'rgba(252, 231, 243, 1)', 'pink-200': 'rgba(251, 207, 232, 1)', 'pink-300': 'rgba(249, 168, 212, 1)', 'pink-400': 'rgba(244, 114, 182, 1)', 'pink-500': 'rgba(236, 72, 153, 1)', 'pink-600': 'rgba(219, 39, 119, 1)', 'pink-700': 'rgba(190, 24, 93, 1)', 'pink-800': 'rgba(157, 23, 77, 1)', 'pink-900': 'rgba(131, 24, 67, 1)', },};
const spacing = { keys: { mr: 'marginRight', ml: 'marginLeft', mt: 'marginTop', mb: 'marginBottom', mx: ['marginLeft', 'marginRight'], my: ['marginTop', 'marginBottom'], m: 'margin', pr: 'paddingRight', pl: 'paddingLeft', pt: 'paddingTop', pb: 'paddingBottom', px: ['paddingLeft', 'paddingRight'], py: ['paddingTop', 'paddingBottom'], p: 'padding', }, values: { auto: 'auto', 0: '0px', px: '1px', 0.5: '0.125rem', 1: '0.25rem', 1.5: '0.375rem', 2: '0.5rem', 2.5: '0.625rem', 3: '0.75rem', 3.5: '0.875rem', 4: '1rem', 5: '1.25rem', 6: '1.5rem', 7: '1.75rem', 8: '2rem', 9: '2.25rem', 10: '2.5rem', 11: '2.75rem', 12: '3rem', 14: '3.5rem', 16: '4rem', 20: '5rem', 24: '6rem', 28: '7rem', 32: '8rem', 36: '9rem', 40: '10rem', 44: '11rem', 48: '12rem', 52: '13rem', 56: '14rem', 60: '15rem', 64: '16rem', 72: '18rem', 80: '20rem', 96: '24rem', },};
const radius = { keys: { rounded: 'borderRadius', 'rounded-t': 'borderTopRadius', 'rounded-r': 'borderRightRadius', 'rounded-l': 'borderLeftRadius', 'rounded-b': 'borderBottomRadius', 'rounded-tl': ['borderTopRadius', 'borderLeftRadius'], 'rounded-tr': ['borderTopRadius', 'borderRightRadius'], 'rounded-bl': ['borderBottomRadius', 'borderLeftRadius'], 'rounded-br': ['borderBottomRadius', 'borderRightRadius'], }, values: { none: '0px', sm: '0.125rem', '': '0.25rem', md: '0.375rem', lg: '0.5rem', xl: '0.75rem', '2xl': '1rem', '3xl': '1.5rem', full: '9999px', },};
const borders = { keys: { border: 'borderWidth', 'border-l': 'borderLeftWidth', 'border-r': 'borderRightWidth', 'border-t': 'borderTopWidth', 'border-b': 'borderBottomWidth', }, values: { '': '1px', 0: '0px', 2: '2px', 4: '4px', 8: '8px', },};
const sizes = { keys: { h: 'height', w: 'width', top: 'top', left: 'left', bottom: 'bottom', right: 'right', minh: 'minHeight', minw: 'minWidth', maxh: 'maxHeight', maxw: 'maxWidth', }, values: { 0: '0px', px: '1px', 0.5: '0.125rem', 1: '0.25rem', 1.5: '0.375rem', 2: '0.5rem', 2.5: '0.625rem', 3: '0.75rem', 3.5: '0.875rem', 4: '1rem', 5: '1.25rem', 6: '1.5rem', 7: '1.75rem', 8: '2rem', 9: '2.25rem', 10: '2.5rem', 11: '2.75rem', 12: '3rem', 14: '3.5rem', 16: '4rem', 20: '5rem', 24: '6rem', 28: '7rem', 32: '8rem', 36: '9rem', 40: '10rem', 44: '11rem', 48: '12rem', 52: '13rem', 56: '14rem', 60: '15rem', 64: '16rem', 72: '18rem', 80: '20rem', 96: '24rem', auto: 'auto', min: 'min-content', max: 'max-content', '1/2': percent(1 / 2), '1/4': percent(1 / 4), '2/4': percent(2 / 4), '3/4': percent(3 / 4), '1/5': percent(1 / 5), '2/5': percent(2 / 5), '3/5': percent(3 / 5), '4/5': percent(4 / 5), '1/6': percent(1 / 6), '2/6': percent(2 / 6), '3/6': percent(3 / 6), '4/6': percent(4 / 6), '5/6': percent(5 / 6), '1/12': percent(1 / 12), '2/12': percent(2 / 12), '3/12': percent(3 / 12), '4/12': percent(4 / 12), '5/12': percent(5 / 12), '6/12': percent(6 / 12), '7/12': percent(7 / 12), '8/12': percent(8 / 12), '9/12': percent(9 / 12), '10/12': percent(10 / 12), '11/12': percent(11 / 12), full: percent(1), },};
const classLookup = { flex: createStyle('display', 'flex'), 'inline-flex': createStyle('display', 'inline-flex'), block: createStyle('display', 'block'), 'inline-block': createStyle('display', 'inline-block'), inline: createStyle('display', 'inline'), table: createStyle('display', 'table'), 'inline-table': createStyle('display', 'inline-table'), 'inline-table': createStyle('display', 'inline-table'), grid: createStyle('display', 'grid'), 'inline-grid': createStyle('display', 'inline-grid'), contents: createStyle('display', 'contents'), 'list-item': createStyle('display', 'list-item'), hidden: createStyle('display', 'none'), 'flex-1': createStyle('flex', '1'), 'flex-row': createStyle('flexDirection', 'row'), 'flex-col': createStyle('flexDirection', 'column'), 'flex-wrap': createStyle('flexWrap', 'wrap'), 'flex-nowrap': createStyle('flexWrap', 'nowrap'), 'flex-wrap-reverse': createStyle('flexWrap', 'wrap-reverse'), 'items-baseline': createStyle('alignItems', 'baseline'), 'items-start': createStyle('alignItems', 'flex-start'), 'items-center': createStyle('alignItems', 'center'), 'items-end': createStyle('alignItems', 'flex-end'), 'items-stretch': createStyle('alignItems', 'stretch'), 'justify-start': createStyle('justifyContent', 'flex-start'), 'justify-end': createStyle('justifyContent', 'flex-end'), 'justify-center': createStyle('justifyContent', 'center'), 'justify-between': createStyle('justifyContent', 'space-between'), 'justify-around': createStyle('justifyContent', 'space-around'), 'justify-evenly': createStyle('justifyContent', 'space-evenly'), 'text-left': createStyle('textAlign', 'left'), 'text-center': createStyle('textAlign', 'center'), 'text-right': createStyle('textAlign', 'right'), 'text-justify': createStyle('textAlign', 'justify'), underline: createStyle('textDecoration', 'underline'), 'line-through': createStyle('textDecoration', 'line-through'), 'no-underline': createStyle('textDecoration', 'none'), 'whitespace-normal': createStyle('whiteSpace', 'normal'), 'whitespace-nowrap': createStyle('whiteSpace', 'nowrap'), 'whitespace-pre': createStyle('whiteSpace', 'pre'), 'whitespace-pre-line': createStyle('whiteSpace', 'pre-line'), 'whitespace-pre-wrap': createStyle('whiteSpace', 'pre-wrap'), 'break-normal': createStyle('wordBreak', 'normal', 'overflowWrap', 'normal'), 'break-words': createStyle('wordBreak', 'break-word'), 'break-all': createStyle('wordBreak', 'break-all'), 'font-sans': createStyle( 'fontFamily', `ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"`, ), 'font-serif': createStyle('fontFamily', `ui-serif, Georgia, Cambria, "Times New Roman", Times, serif`), 'font-mono': createStyle('fontFamily', `ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`), 'font-thin': createStyle('fontWeight', '100'), 'font-extralight': createStyle('fontWeight', '200'), 'font-light': createStyle('fontWeight', '300'), 'font-normal': createStyle('fontWeight', '400'), 'font-medium': createStyle('fontWeight', '500'), 'font-semibold': createStyle('fontWeight', '600'), 'font-bold': createStyle('fontWeight', '700'), 'font-extrabold': createStyle('fontWeight', '800'), 'font-black': createStyle('fontWeight', '900'), 'text-xs': createStyle('fontSize', '0.75rem', 'lineHeight', '1rem'), 'text-sm': createStyle('fontSize', '0.875rem', 'lineHeight', '1.25rem'), 'text-base': createStyle('fontSize', '1rem', 'lineHeight', '1.5rem'), 'text-lg': createStyle('fontSize', '1.125rem', 'lineHeight', '1.75rem'), 'text-xl': createStyle('fontSize', '1.25rem', 'lineHeight', '1.75rem'), 'text-2xl': createStyle('fontSize', '1.5rem', 'lineHeight', '2rem'), 'text-3xl': createStyle('fontSize', '1.875rem', 'lineHeight', '2.25rem'), 'text-4xl': createStyle('fontSize', '2.25rem', 'lineHeight', '2.5rem'), 'text-5xl': createStyle('fontSize', '3rem', 'lineHeight', '1'), 'text-6xl': createStyle('fontSize', '3.75rem;', 'lineHeight', '1'), 'text-7xl': createStyle('fontSize', '4.5rem', 'lineHeight', '1'), 'text-8xl': createStyle('fontSize', '6rem', 'lineHeight', '1'), 'text-9xl': createStyle('fontSize', '8rem', 'lineHeight', '1'), 'cursor-auto': createStyle('cursor', 'auto'), 'cursor-default': createStyle('cursor', 'default'), 'cursor-pointer': createStyle('cursor', 'pointer'), 'cursor-wait': createStyle('cursor', 'wait'), 'cursor-text': createStyle('cursor', 'text'), 'cursor-move': createStyle('cursor', 'move'), 'cursor-help': createStyle('cursor', 'help'), 'cursor-not-allowed': createStyle('cursor', 'not-allowed'), 'pointer-events-none': createStyle('pointerEvents', 'none'), 'pointer-events-auto': createStyle('pointerEvents', 'auto'), 'select-none': createStyle('userSelect', 'none'), 'select-text': createStyle('userSelect', 'text'), 'select-all': createStyle('userSelect', 'all'), 'select-auto': createStyle('userSelect', 'auto'), 'w-screen': '100vw', 'h-screen': '100vh', ...mapApply(sizes), ...mapApply(spacing), ...mapApply(colors), ...mapApply(borders), ...mapApply(radius), static: createStyle('position', 'static'), fixed: createStyle('position', 'fixed'), absolute: createStyle('position', 'absolute'), relative: createStyle('position', 'relative'), sticky: createStyle('position', 'sticky'), 'overflow-auto': createStyle('overflow', 'auto'), 'overflow-hidden': createStyle('overflow', 'hidden'), 'overflow-visible': createStyle('overflow', 'visible'), 'overflow-scroll': createStyle('overflow', 'scroll'), 'overflow-x-auto': createStyle('overflowX', 'auto'), 'overflow-y-auto': createStyle('overflowY', 'auto'), 'overflow-x-hidden': createStyle('overflowX', 'hidden'), 'overflow-y-hidden': createStyle('overflowY', 'hidden'), 'overflow-x-visible': createStyle('overflowX', 'visible'), 'overflow-y-visible': createStyle('overflowY', 'visible'), 'overflow-x-scroll': createStyle('overflowX', 'scroll'), 'overflow-y-scroll': createStyle('overflowY', 'scroll'), 'origin-center': createStyle('transformOrigin', 'center'), 'origin-top': createStyle('transformOrigin', 'top'), 'origin-top-right': createStyle('transformOrigin', 'top right'), 'origin-right': createStyle('transformOrigin', 'right'), 'origin-bottom-right': createStyle('transformOrigin', 'bottom right'), 'origin-bottom': createStyle('transformOrigin', 'bottom'), 'origin-bottom-left': createStyle('transformOrigin', 'bottom left'), 'origin-left': createStyle('transformOrigin', 'left'), 'origin-top-left': createStyle('transformOrigin', 'top left'), 'shadow-sm': createStyle('box-shadow', '0 0 #0000, 0 0 #0000, 0 1px 2px 0 rgba(0, 0, 0, 0.05)'), shadow: createStyle('box-shadow', '0 0 #0000, 0 0 #0000, 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)'), 'shadow-md': createStyle('box-shadow', '0 0 #0000, 0 0 #0000, 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)'), 'shadow-lg': createStyle('box-shadow', '0 0 #0000, 0 0 #0000, 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)'), 'shadow-xl': createStyle('box-shadow', '0 0 #0000, 0 0 #0000, 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)'), 'shadow-2xl': createStyle('box-shadow', '0 0 #0000, 0 0 #0000, 0 25px 50px -12px rgba(0, 0, 0, 0.25)'), 'shadow-inner': createStyle('box-shadow', '0 0 #0000, 0 0 #0000, inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)'), 'shadow-none': createStyle('box-shadow', '0 0 #0000, 0 0 #0000, 0 0 #0000'), 'ring-inset': createStyle('--tw-ring-inset', 'insest'), 'ring-0': createStyle('box-shadow', ' 0 0 0 calc(0px + 0px) rgba(59, 130, 246, 0.5)'), 'ring-1': createStyle('box-shadow', ' 0 0 0 calc(1px + 0px) rgba(59, 130, 246, 0.5)'), 'ring-2': createStyle('box-shadow', ' 0 0 0 calc(2px + 0px) rgba(59, 130, 246, 0.5)'), 'ring-4': createStyle('box-shadow', ' 0 0 0 calc(4px + 0px) rgba(59, 130, 246, 0.5)'), 'ring-8': createStyle('box-shadow', ' 0 0 0 calc(8px + 0px) rgba(59, 130, 246, 0.5)'), ring: createStyle('box-shadow', ' 0 0 0 calc(3px + 0px) rgba(59, 130, 246, 0.5)'),};
const pageStyles = { '*, ::before, ::after': { boxSizing: 'border-box', borderWidth: '0', borderStyle: 'solid', borderColor: '#e5e7eb', }, hr: { height: '0', color: 'inherit', borderTopWidth: '1px' }, 'abbr[title]': { WebkitTextDecoration: 'underline dotted', textDecoration: 'underline dotted', }, 'b, strong': { fontWeight: 'bolder' }, 'code, kbd, samp, pre': { fontFamily: "ui-monospace, SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace", fontSize: '1em', }, small: { fontSize: '80%' }, 'sub, sup': { fontSize: '75%', lineHeight: 0, position: 'relative', verticalAlign: 'baseline', }, sub: { bottom: '-0.25em' }, sup: { top: '-0.5em' }, table: { textIndent: '0', borderColor: 'inherit', borderCollapse: 'collapse', }, 'button, input, optgroup, select, textarea': { fontSize: '100%', margin: '0', padding: '0', lineHeight: 'inherit', color: 'inherit', }, 'button, select': {}, "button, [type='button'], [type='reset'], [type='submit']": {}, '::-moz-focus-inner': { borderStyle: 'none', padding: '0' }, ':-moz-focusring': { outline: '1px dotted ButtonText' }, ':-moz-ui-invalid': { boxShadow: 'none' }, legend: { padding: '0' }, progress: { verticalAlign: 'baseline' }, '::-webkit-inner-spin-button, ::-webkit-outer-spin-button': { height: 'auto', }, "[type='search']": { WebkitAppearance: 'textfield', outlineOffset: '-2px' }, '::-webkit-search-decoration': { WebkitAppearance: 'none' }, '::-webkit-file-upload-button': { WebkitAppearance: 'button', font: 'inherit', }, summary: { display: 'list-item' }, 'blockquote, dl, dd, h1, h2, h3, h4, h5, h6, hr, figure, p, pre': { margin: '0', }, button: { backgroundImage: 'none', ':focus': { outline: '1px dotted, 5px auto -webkit-focus-ring-color', }, }, fieldset: { margin: '0', padding: '0' }, 'ol, ul': { listStyle: 'none', margin: '0', padding: '0' }, img: { borderStyle: 'solid' }, textarea: { resize: 'vertical' }, 'input::-moz-placeholder, textarea::-moz-placeholder': { opacity: 1, color: '#9ca3af', }, 'input:-ms-input-placeholder, textarea:-ms-input-placeholder': { opacity: 1, color: '#9ca3af', }, 'input::placeholder, textarea::placeholder': { opacity: 1, color: '#9ca3af', }, "button, [role='button']": { cursor: 'pointer' }, 'h1, h2, h3, h4, h5, h6': { fontSize: 'inherit', fontWeight: 'inherit' }, a: { color: 'inherit', textDecoration: 'inherit' }, 'pre, code, kbd, samp': { fontFamily: "ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace", }, 'img, svg, video, canvas, audio, iframe, embed, object': { display: 'block', verticalAlign: 'middle', }, 'img, video': { maxWidth: '100%', height: 'auto' }, html: { MozTabSize: '4', OTabSize: '4', tabSize: 4, lineHeight: 1.5, WebkitTextSizeAdjust: '100%', fontFamily: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'", width: '100%', height: '100%', }, body: { margin: '0px', fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif", lineHeight: 1.4, backgroundColor: 'white', width: '100%', height: '100%', display: 'flex', flexDirection: 'column', flex: '1 1 0%', minWidth: '320px', minHeight: '100vh', fontWeight: 400, color: 'rgba(44, 62, 80, 1)', direction: 'ltr', fontSynthesis: 'none', textRendering: 'optimizeLegibility', },};
// hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500
const previousValues = new WeakMap();export const unsafeHTML = isBrowser ? directive((value) => (part) => { if (!(part instanceof NodePart)) { throw new Error('unsafeHTML can only be used in text bindings'); } const previousValue = previousValues.get(part); if (previousValue !== undefined && isPrimitive(value) && value === previousValue.value && part.value === previousValue.fragment) { return; } const template = document.createElement('template'); template.innerHTML = value; // innerHTML casts to string internally const fragment = document.importNode(template.content, true); part.setValue(fragment); previousValues.set(part, { value, fragment }); }) : (value) => value;
const fifo = (q) => q.shift();const filo = (q) => q.pop();const microtask = (flush) => () => queueMicrotask(flush);const task = (flush) => { if (isBrowser) { const ch = new window.MessageChannel(); ch.port1.onmessage = flush; return () => ch.port2.postMessage(null); } else { return () => setImmediate(flush); }};const depsChanged = (prev, next) => prev == null || next.some((f, i) => !Object.is(f, prev[i]));
export const createAttrs = (attrs) => attrs;
export const createReducer = ({ initial, reducer, effects }) => { let value = initial; const subs = new Set(); const actions = Object.keys(reducer).reduce((acc, key) => { const reduce = reducer[key]; acc[key] = (v) => { value = reduce(value, v); subs.forEach((sub) => { sub(value); }); }; return acc; }, {}); const effectActions = Object.keys(effects || {}).reduce((acc, key) => { const effect = effects[key]; acc[key] = (v) => effect(actions, v); return acc; }, {}); return { getValue: () => value, subscribe: (fn) => { subs.add(fn); }, unsubscribe: (fn) => { subs.remove(fn); }, actions, effects: effectActions, };};
const currentComponent = { current: undefined, set(v) { this.current = v; this.current.hooks.index = 0; }, get() { return this.current; },};
export const useReducer = (reducer) => { const comp = currentComponent.get(); const index = comp.hooks.index++; if (!comp.hooks.data[index]) { comp.hooks.data[index] = reducer.subscribe ? reducer : createReducer(reducer); comp.hooks.data[index].subscribe(() => comp.update()); } const state = comp.hooks.data[index].getValue(); return { ...state, actions: comp.hooks.data[index].actions, effects: comp.hooks.data[index].effects };};export const useEffect = (fn, deps) => { const comp = currentComponent.get(); const index = comp.hooks.index++; if (!deps || depsChanged(comp.hooks.deps[index], deps)) { comp.hooks.deps[index] = deps || []; comp.hooks.effects[index] = fn; }};
const registry = {};export const getElement = (name) => registry[name];const BaseElement = isBrowser ? window.HTMLElement : class {};export const createElement = (meta, renderFn) => { const funcParams = parseFuncParams(renderFn); const RenderElement = class extends BaseElement { static get observedAttributes() { return funcParams.map((k) => k.toLowerCase()); }
constructor(ssrAttrs) { super(); this._dirty = false; this._connected = false; this.attrs = ssrAttrs || {}; this.state = {}; this.hooks = { index: 0, data: {}, deps: {}, effects: {}, cleanups: {}, }; this.renderFn = renderFn; // this.prevClassList = []; // this.shadow = this.attachShadow({ mode: 'open' }); }
connectedCallback() { this._connected = true; this.update(); }
disconnectedCallback() { this._connected = false; }
attributeChangedCallback(key, oldValue, newValue) { this.attrs[key] = newValue && newValue.startsWith(`{`) ? JSON.parse(newValue.replace(/'/g, `"`)) : newValue; if (this._connected) { this.update(); } }
update() { if (this._dirty) { return; } this._dirty = true; this.enqueueUpdate(); }
_performUpdate() { if (!this._connected) { return; } this.render(); this.enqueueEffects(); this._dirty = false; }
_flushEffects() { const effects = this.hooks.effects; const cleanups = this.hooks.cleanups; const keys = Object.keys(effects); for (const key of keys) { if (effects[key]) { cleanups[key] && cleanups[key](); const cleanup = effects[key](); if (cleanup) { cleanups[key] = cleanup; } delete effects[key]; } } }
batch(runner, pick, callback) { const q = []; const flush = () => { let p; while ((p = pick(q))) callback(p); }; const run = runner(flush); q.push(this) === 1 && run(); }
enqueueUpdate() { this.batch(microtask, fifo, () => this._performUpdate()); }
enqueueEffects() { this.batch(task, filo, () => this._flushEffects()); }
render() { currentComponent.set(this); const template = this.renderFn({ ...this.attrs, config: isBrowser ? window.props.config : global?.props?.config, location: isBrowser ? window.location : global?.location, }); if (isBrowser) { // TODO: this can be optimized when we know whether the value belongs in a class (AttributePart) // maybe do this in lit-html itselfs const newClassList = getClassList(template).filter((cls) => { const globalStyles = document.getElementById('global').textContent; return !globalStyles.includes('.' + cls); }); if (newClassList.length > 0) { document.getElementById('global').textContent += compileTw(newClassList); } renderHtml(template, this); // For shadows only // if (!this.styleElement) { // render(template, this.shadow); // const styleSheet = compileTw(classList); // this.prevClassList = classList; // this.styleElement = document.createElement('style'); // this.shadow.appendChild(this.styleElement).textContent = css(pageStyles) + styleSheet; // } else { // const missingClassList = classList.filter((cls) => !this.prevClassList.includes(cls)); // if (missingClassList.length > 0) { // const styleSheet = compileTw(missingClassList); // this.styleElement.textContent += '\n' + styleSheet; // this.prevClassList.push(...missingClassList); // } // render(template, this.shadow); // } } else { return renderHtml(template); } } }; const parts = meta.url.split('/'); const name = parts[parts.length - 1].split('?')[0].replace('.js', ''); registry[name] = RenderElement; if (isBrowser && !window.customElements.get(name)) { window.customElements.define(name, registry[name]); } return renderFn;};
export const createPage = ({ head, body }) => { return ({ headScript, bodyScript, lang, props }) => { const headHtml = renderHtml(head(props)); const bodyHtml = renderHtml(body(props)); const classes = extractClasses(bodyHtml); return ` <!DOCTYPE html> <html lang="${lang}"> <head> <meta charset="utf-8" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=5.0, shrink-to-fit=no"> <link rel="sitemap" type="application/xml" href="/sitemap.xml" /> <link rel="icon" type="image/png" href="/assets/icon.png" /> ${headHtml} <style id="global"> ${css(pageStyles)} ${compileTw(new Set(classes.split(' ')))} </style> ${headScript} </head> <body> ${bodyHtml} <script> window.props = ${JSON.stringify(props)}; </script> ${bodyScript} </body> </html> `; };};