// ==UserScript== // @name Cotrans Manga/Image Translator (Regular Edition) // @name:zh-CN Cotrans 漫画/图片翻译器 (常规版) // @namespace https://cotrans.touhou.ai/userscript/#regular // @version 0.8.0-bata.17 // @description (WIP) Translate texts in images on Pixiv, Twitter, Misskey, Calckey // @description:zh-CN (WIP) 一键翻译图片内文字,支持 Pixiv, Twitter, Misskey, Calckey // @author QiroNT // @license GPL-3.0 // @contributionURL https://ko-fi.com/voilelabs // @supportURL https://discord.gg/975FRV8ca6 // @source https://cotrans.touhou.ai/ // @include https://www.pixiv.net/* // @match https://www.pixiv.net/* // @include https://twitter.com/* // @match https://twitter.com/* // @include https://misskey.io/* // @match https://misskey.io/* // @include https://calckey.social/* // @match https://calckey.social/* // @include https://* // @match https://* // @connect pixiv.net // @connect pximg.net // @connect twitter.com // @connect twimg.com // @connect misskey.io // @connect misskeyusercontent.com // @connect s3.arkjp.net // @connect nfs.pub // @connect calckey.social // @connect backblazeb2.com // @connect dvd.moe // @connect api.cotrans.touhou.ai // @connect r2.cotrans.touhou.ai // @connect cotrans-r2.moe.ci // @connect * // @grant GM.xmlHttpRequest // @grant GM_xmlhttpRequest // @grant GM.setValue // @grant GM_setValue // @grant GM.getValue // @grant GM_getValue // @grant GM.deleteValue // @grant GM_deleteValue // @grant GM.addValueChangeListener // @grant GM_addValueChangeListener // @grant GM.removeValueChangeListener // @grant GM_removeValueChangeListener // @grant window.onurlchange // @run-at document-idle // @downloadURL none // ==/UserScript== /* eslint-disable no-undef, unused-imports/no-unused-vars */ const VERSION = '0.8.0-bata.17' const EDITION = 'regular' let GMP { // polyfill functions const GMPFunctionMap = { xmlHttpRequest: typeof GM_xmlhttpRequest !== 'undefined' ? GM_xmlhttpRequest : undefined, setValue: typeof GM_setValue !== 'undefined' ? GM_setValue : undefined, getValue: typeof GM_getValue !== 'undefined' ? GM_getValue : undefined, deleteValue: typeof GM_deleteValue !== 'undefined' ? GM_deleteValue : undefined, addValueChangeListener: typeof GM_addValueChangeListener !== 'undefined' ? GM_addValueChangeListener : undefined, removeValueChangeListener: typeof GM_removeValueChangeListener !== 'undefined' ? GM_removeValueChangeListener : undefined, } const xmlHttpRequest = GM.xmlHttpRequest.bind(GM) || GMPFunctionMap.xmlHttpRequest GMP = new Proxy(GM, { get(target, prop) { if (prop === 'xmlHttpRequest') { return (context) => { return new Promise((resolve, reject) => { xmlHttpRequest({ ...context, onload(event) { context.onload?.() resolve(event) }, onerror(event) { context.onerror?.() reject(event) }, }) }) } } if (prop in target) { const v = target[prop] return typeof v === 'function' ? v.bind(target) : v } if (prop in GMPFunctionMap && typeof GMPFunctionMap[prop] === 'function') return GMPFunctionMap[prop] console.error(`[Cotrans Manga Translator] GM.${prop} isn't supported in your userscript engine and it's required by this script. This may lead to unexpected behavior.`) }, }) } (function () { 'use strict'; const equalFn = (a, b) => a === b; const $PROXY = Symbol("solid-proxy"); const $TRACK = Symbol("solid-track"); const $DEVCOMP = Symbol("solid-dev-component"); const signalOptions = { equals: equalFn }; let runEffects = runQueue; const STALE = 1; const PENDING = 2; const UNOWNED = { owned: null, cleanups: null, context: null, owner: null }; var Owner = null; let Transition = null; let Listener = null; let Updates = null; let Effects = null; let ExecCount = 0; function createRoot(fn, detachedOwner) { const listener = Listener, owner = Owner, unowned = fn.length === 0, root = unowned ? UNOWNED : { owned: null, cleanups: null, context: null, owner: detachedOwner === undefined ? owner : detachedOwner }, updateFn = unowned ? fn : () => fn(() => untrack(() => cleanNode(root))); Owner = root; Listener = null; try { return runUpdates(updateFn, true); } finally { Listener = listener; Owner = owner; } } function createSignal(value, options) { options = options ? Object.assign({}, signalOptions, options) : signalOptions; const s = { value, observers: null, observerSlots: null, comparator: options.equals || undefined }; const setter = value => { if (typeof value === "function") { value = value(s.value); } return writeSignal(s, value); }; return [readSignal.bind(s), setter]; } function createRenderEffect(fn, value, options) { const c = createComputation(fn, value, false, STALE); updateComputation(c); } function createEffect(fn, value, options) { runEffects = runUserEffects; const c = createComputation(fn, value, false, STALE); if (!options || !options.render) c.user = true; Effects ? Effects.push(c) : updateComputation(c); } function createMemo(fn, value, options) { options = options ? Object.assign({}, signalOptions, options) : signalOptions; const c = createComputation(fn, value, true, 0); c.observers = null; c.observerSlots = null; c.comparator = options.equals || undefined; updateComputation(c); return readSignal.bind(c); } function batch(fn) { return runUpdates(fn, false); } function untrack(fn) { if (Listener === null) return fn(); const listener = Listener; Listener = null; try { return fn(); } finally { Listener = listener; } } function on(deps, fn, options) { const isArray = Array.isArray(deps); let prevInput; let defer = options && options.defer; return prevValue => { let input; if (isArray) { input = Array(deps.length); for (let i = 0; i < deps.length; i++) input[i] = deps[i](); } else input = deps(); if (defer) { defer = false; return undefined; } const result = untrack(() => fn(input, prevInput, prevValue)); prevInput = input; return result; }; } function onMount(fn) { createEffect(() => untrack(fn)); } function onCleanup(fn) { if (Owner === null) ;else if (Owner.cleanups === null) Owner.cleanups = [fn];else Owner.cleanups.push(fn); return fn; } function getListener() { return Listener; } function getOwner() { return Owner; } function children(fn) { const children = createMemo(fn); const memo = createMemo(() => resolveChildren(children())); memo.toArray = () => { const c = memo(); return Array.isArray(c) ? c : c != null ? [c] : []; }; return memo; } function readSignal() { if (this.sources && (this.state)) { if ((this.state) === STALE) updateComputation(this);else { const updates = Updates; Updates = null; runUpdates(() => lookUpstream(this), false); Updates = updates; } } if (Listener) { const sSlot = this.observers ? this.observers.length : 0; if (!Listener.sources) { Listener.sources = [this]; Listener.sourceSlots = [sSlot]; } else { Listener.sources.push(this); Listener.sourceSlots.push(sSlot); } if (!this.observers) { this.observers = [Listener]; this.observerSlots = [Listener.sources.length - 1]; } else { this.observers.push(Listener); this.observerSlots.push(Listener.sources.length - 1); } } return this.value; } function writeSignal(node, value, isComp) { let current = node.value; if (!node.comparator || !node.comparator(current, value)) { node.value = value; if (node.observers && node.observers.length) { runUpdates(() => { for (let i = 0; i < node.observers.length; i += 1) { const o = node.observers[i]; const TransitionRunning = Transition && Transition.running; if (TransitionRunning && Transition.disposed.has(o)) ; if (TransitionRunning ? !o.tState : !o.state) { if (o.pure) Updates.push(o);else Effects.push(o); if (o.observers) markDownstream(o); } if (!TransitionRunning) o.state = STALE; } if (Updates.length > 10e5) { Updates = []; if (false) ; throw new Error(); } }, false); } } return value; } function updateComputation(node) { if (!node.fn) return; cleanNode(node); const owner = Owner, listener = Listener, time = ExecCount; Listener = Owner = node; runComputation(node, node.value, time); Listener = listener; Owner = owner; } function runComputation(node, value, time) { let nextValue; try { nextValue = node.fn(value); } catch (err) { if (node.pure) { { node.state = STALE; node.owned && node.owned.forEach(cleanNode); node.owned = null; } } node.updatedAt = time + 1; return handleError(err); } if (!node.updatedAt || node.updatedAt <= time) { if (node.updatedAt != null && "observers" in node) { writeSignal(node, nextValue); } else node.value = nextValue; node.updatedAt = time; } } function createComputation(fn, init, pure, state = STALE, options) { const c = { fn, state: state, updatedAt: null, owned: null, sources: null, sourceSlots: null, cleanups: null, value: init, owner: Owner, context: null, pure }; if (Owner === null) ;else if (Owner !== UNOWNED) { { if (!Owner.owned) Owner.owned = [c];else Owner.owned.push(c); } } return c; } function runTop(node) { if ((node.state) === 0) return; if ((node.state) === PENDING) return lookUpstream(node); if (node.suspense && untrack(node.suspense.inFallback)) return node.suspense.effects.push(node); const ancestors = [node]; while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) { if (node.state) ancestors.push(node); } for (let i = ancestors.length - 1; i >= 0; i--) { node = ancestors[i]; if ((node.state) === STALE) { updateComputation(node); } else if ((node.state) === PENDING) { const updates = Updates; Updates = null; runUpdates(() => lookUpstream(node, ancestors[0]), false); Updates = updates; } } } function runUpdates(fn, init) { if (Updates) return fn(); let wait = false; if (!init) Updates = []; if (Effects) wait = true;else Effects = []; ExecCount++; try { const res = fn(); completeUpdates(wait); return res; } catch (err) { if (!wait) Effects = null; Updates = null; handleError(err); } } function completeUpdates(wait) { if (Updates) { runQueue(Updates); Updates = null; } if (wait) return; const e = Effects; Effects = null; if (e.length) runUpdates(() => runEffects(e), false); } function runQueue(queue) { for (let i = 0; i < queue.length; i++) runTop(queue[i]); } function runUserEffects(queue) { let i, userLength = 0; for (i = 0; i < queue.length; i++) { const e = queue[i]; if (!e.user) runTop(e);else queue[userLength++] = e; } for (i = 0; i < userLength; i++) runTop(queue[i]); } function lookUpstream(node, ignore) { node.state = 0; for (let i = 0; i < node.sources.length; i += 1) { const source = node.sources[i]; if (source.sources) { const state = source.state; if (state === STALE) { if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount)) runTop(source); } else if (state === PENDING) lookUpstream(source, ignore); } } } function markDownstream(node) { for (let i = 0; i < node.observers.length; i += 1) { const o = node.observers[i]; if (!o.state) { o.state = PENDING; if (o.pure) Updates.push(o);else Effects.push(o); o.observers && markDownstream(o); } } } function cleanNode(node) { let i; if (node.sources) { while (node.sources.length) { const source = node.sources.pop(), index = node.sourceSlots.pop(), obs = source.observers; if (obs && obs.length) { const n = obs.pop(), s = source.observerSlots.pop(); if (index < obs.length) { n.sourceSlots[s] = index; obs[index] = n; source.observerSlots[index] = s; } } } } if (node.owned) { for (i = node.owned.length - 1; i >= 0; i--) cleanNode(node.owned[i]); node.owned = null; } if (node.cleanups) { for (i = node.cleanups.length - 1; i >= 0; i--) node.cleanups[i](); node.cleanups = null; } node.state = 0; node.context = null; } function castError(err) { if (err instanceof Error) return err; return new Error(typeof err === "string" ? err : "Unknown error", { cause: err }); } function handleError(err, owner = Owner) { const error = castError(err); throw error; } function resolveChildren(children) { if (typeof children === "function" && !children.length) return resolveChildren(children()); if (Array.isArray(children)) { const results = []; for (let i = 0; i < children.length; i++) { const result = resolveChildren(children[i]); Array.isArray(result) ? results.push.apply(results, result) : results.push(result); } return results; } return children; } const FALLBACK = Symbol("fallback"); function dispose(d) { for (let i = 0; i < d.length; i++) d[i](); } function mapArray(list, mapFn, options = {}) { let items = [], mapped = [], disposers = [], len = 0, indexes = mapFn.length > 1 ? [] : null; onCleanup(() => dispose(disposers)); return () => { let newItems = list() || [], i, j; newItems[$TRACK]; return untrack(() => { let newLen = newItems.length, newIndices, newIndicesNext, temp, tempdisposers, tempIndexes, start, end, newEnd, item; if (newLen === 0) { if (len !== 0) { dispose(disposers); disposers = []; items = []; mapped = []; len = 0; indexes && (indexes = []); } if (options.fallback) { items = [FALLBACK]; mapped[0] = createRoot(disposer => { disposers[0] = disposer; return options.fallback(); }); len = 1; } } else if (len === 0) { mapped = new Array(newLen); for (j = 0; j < newLen; j++) { items[j] = newItems[j]; mapped[j] = createRoot(mapper); } len = newLen; } else { temp = new Array(newLen); tempdisposers = new Array(newLen); indexes && (tempIndexes = new Array(newLen)); for (start = 0, end = Math.min(len, newLen); start < end && items[start] === newItems[start]; start++); for (end = len - 1, newEnd = newLen - 1; end >= start && newEnd >= start && items[end] === newItems[newEnd]; end--, newEnd--) { temp[newEnd] = mapped[end]; tempdisposers[newEnd] = disposers[end]; indexes && (tempIndexes[newEnd] = indexes[end]); } newIndices = new Map(); newIndicesNext = new Array(newEnd + 1); for (j = newEnd; j >= start; j--) { item = newItems[j]; i = newIndices.get(item); newIndicesNext[j] = i === undefined ? -1 : i; newIndices.set(item, j); } for (i = start; i <= end; i++) { item = items[i]; j = newIndices.get(item); if (j !== undefined && j !== -1) { temp[j] = mapped[i]; tempdisposers[j] = disposers[i]; indexes && (tempIndexes[j] = indexes[i]); j = newIndicesNext[j]; newIndices.set(item, j); } else disposers[i](); } for (j = start; j < newLen; j++) { if (j in temp) { mapped[j] = temp[j]; disposers[j] = tempdisposers[j]; if (indexes) { indexes[j] = tempIndexes[j]; indexes[j](j); } } else mapped[j] = createRoot(mapper); } mapped = mapped.slice(0, len = newLen); items = newItems.slice(0); } return mapped; }); function mapper(disposer) { disposers[j] = disposer; if (indexes) { const [s, set] = createSignal(j); indexes[j] = set; return mapFn(newItems[j], s); } return mapFn(newItems[j]); } }; } function createComponent(Comp, props) { return untrack(() => Comp(props || {})); } function trueFn() { return true; } const propTraps = { get(_, property, receiver) { if (property === $PROXY) return receiver; return _.get(property); }, has(_, property) { if (property === $PROXY) return true; return _.has(property); }, set: trueFn, deleteProperty: trueFn, getOwnPropertyDescriptor(_, property) { return { configurable: true, enumerable: true, get() { return _.get(property); }, set: trueFn, deleteProperty: trueFn }; }, ownKeys(_) { return _.keys(); } }; function splitProps(props, ...keys) { if ($PROXY in props) { const blocked = new Set(keys.length > 1 ? keys.flat() : keys[0]); const res = keys.map(k => { return new Proxy({ get(property) { return k.includes(property) ? props[property] : undefined; }, has(property) { return k.includes(property) && property in props; }, keys() { return k.filter(property => property in props); } }, propTraps); }); res.push(new Proxy({ get(property) { return blocked.has(property) ? undefined : props[property]; }, has(property) { return blocked.has(property) ? false : property in props; }, keys() { return Object.keys(props).filter(k => !blocked.has(k)); } }, propTraps)); return res; } const otherObject = {}; const objects = keys.map(() => ({})); for (const propName of Object.getOwnPropertyNames(props)) { const desc = Object.getOwnPropertyDescriptor(props, propName); const isDefaultDesc = !desc.get && !desc.set && desc.enumerable && desc.writable && desc.configurable; let blocked = false; let objectIndex = 0; for (const k of keys) { if (k.includes(propName)) { blocked = true; isDefaultDesc ? objects[objectIndex][propName] = desc.value : Object.defineProperty(objects[objectIndex], propName, desc); } ++objectIndex; } if (!blocked) { isDefaultDesc ? otherObject[propName] = desc.value : Object.defineProperty(otherObject, propName, desc); } } return [...objects, otherObject]; } const narrowedError = name => `Stale read from <${name}>.`; function For(props) { const fallback = "fallback" in props && { fallback: () => props.fallback }; return createMemo(mapArray(() => props.each, props.children, fallback || undefined)); } function Show(props) { const keyed = props.keyed; const condition = createMemo(() => props.when, undefined, { equals: (a, b) => keyed ? a === b : !a === !b }); return createMemo(() => { const c = condition(); if (c) { const child = props.children; const fn = typeof child === "function" && child.length > 0; return fn ? untrack(() => child(keyed ? c : () => { if (!untrack(condition)) throw narrowedError("Show"); return props.when; })) : child; } return props.fallback; }, undefined, undefined); } function Switch(props) { let keyed = false; const equals = (a, b) => a[0] === b[0] && (keyed ? a[1] === b[1] : !a[1] === !b[1]) && a[2] === b[2]; const conditions = children(() => props.children), evalConditions = createMemo(() => { let conds = conditions(); if (!Array.isArray(conds)) conds = [conds]; for (let i = 0; i < conds.length; i++) { const c = conds[i].when; if (c) { keyed = !!conds[i].keyed; return [i, c, conds[i]]; } } return [-1]; }, undefined, { equals }); return createMemo(() => { const [index, when, cond] = evalConditions(); if (index < 0) return props.fallback; const c = cond.children; const fn = typeof c === "function" && c.length > 0; return fn ? untrack(() => c(keyed ? when : () => { if (untrack(evalConditions)[0] !== index) throw narrowedError("Match"); return cond.when; })) : c; }, undefined, undefined); } function Match(props) { return props; } const booleans = ["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "disabled", "formnovalidate", "hidden", "indeterminate", "ismap", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "seamless", "selected"]; const Properties = /*#__PURE__*/new Set(["className", "value", "readOnly", "formNoValidate", "isMap", "noModule", "playsInline", ...booleans]); const ChildProperties = /*#__PURE__*/new Set(["innerHTML", "textContent", "innerText", "children"]); const Aliases = /*#__PURE__*/Object.assign(Object.create(null), { className: "class", htmlFor: "for" }); const PropAliases = /*#__PURE__*/Object.assign(Object.create(null), { class: "className", formnovalidate: { $: "formNoValidate", BUTTON: 1, INPUT: 1 }, ismap: { $: "isMap", IMG: 1 }, nomodule: { $: "noModule", SCRIPT: 1 }, playsinline: { $: "playsInline", VIDEO: 1 }, readonly: { $: "readOnly", INPUT: 1, TEXTAREA: 1 } }); function getPropAlias(prop, tagName) { const a = PropAliases[prop]; return typeof a === "object" ? a[tagName] ? a["$"] : undefined : a; } const DelegatedEvents = /*#__PURE__*/new Set(["beforeinput", "click", "dblclick", "contextmenu", "focusin", "focusout", "input", "keydown", "keyup", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup", "pointerdown", "pointermove", "pointerout", "pointerover", "pointerup", "touchend", "touchmove", "touchstart"]); const SVGElements = /*#__PURE__*/new Set(["altGlyph", "altGlyphDef", "altGlyphItem", "animate", "animateColor", "animateMotion", "animateTransform", "circle", "clipPath", "color-profile", "cursor", "defs", "desc", "ellipse", "feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence", "filter", "font", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignObject", "g", "glyph", "glyphRef", "hkern", "image", "line", "linearGradient", "marker", "mask", "metadata", "missing-glyph", "mpath", "path", "pattern", "polygon", "polyline", "radialGradient", "rect", "set", "stop", "svg", "switch", "symbol", "text", "textPath", "tref", "tspan", "use", "view", "vkern"]); const SVGNamespace = { xlink: "http://www.w3.org/1999/xlink", xml: "http://www.w3.org/XML/1998/namespace" }; function reconcileArrays(parentNode, a, b) { let bLength = b.length, aEnd = a.length, bEnd = bLength, aStart = 0, bStart = 0, after = a[aEnd - 1].nextSibling, map = null; while (aStart < aEnd || bStart < bEnd) { if (a[aStart] === b[bStart]) { aStart++; bStart++; continue; } while (a[aEnd - 1] === b[bEnd - 1]) { aEnd--; bEnd--; } if (aEnd === aStart) { const node = bEnd < bLength ? bStart ? b[bStart - 1].nextSibling : b[bEnd - bStart] : after; while (bStart < bEnd) parentNode.insertBefore(b[bStart++], node); } else if (bEnd === bStart) { while (aStart < aEnd) { if (!map || !map.has(a[aStart])) a[aStart].remove(); aStart++; } } else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) { const node = a[--aEnd].nextSibling; parentNode.insertBefore(b[bStart++], a[aStart++].nextSibling); parentNode.insertBefore(b[--bEnd], node); a[aEnd] = b[bEnd]; } else { if (!map) { map = new Map(); let i = bStart; while (i < bEnd) map.set(b[i], i++); } const index = map.get(a[aStart]); if (index != null) { if (bStart < index && index < bEnd) { let i = aStart, sequence = 1, t; while (++i < aEnd && i < bEnd) { if ((t = map.get(a[i])) == null || t !== index + sequence) break; sequence++; } if (sequence > index - bStart) { const node = a[aStart]; while (bStart < index) parentNode.insertBefore(b[bStart++], node); } else parentNode.replaceChild(b[bStart++], a[aStart++]); } else aStart++; } else a[aStart++].remove(); } } } const $$EVENTS = "_$DX_DELEGATE"; function render(code, element, init, options = {}) { let disposer; createRoot(dispose => { disposer = dispose; element === document ? code() : insert(element, code(), element.firstChild ? null : undefined, init); }, options.owner); return () => { disposer(); element.textContent = ""; }; } function template(html, isCE, isSVG) { let node; const create = () => { const t = document.createElement("template"); t.innerHTML = html; return isSVG ? t.content.firstChild.firstChild : t.content.firstChild; }; const fn = isCE ? () => untrack(() => document.importNode(node || (node = create()), true)) : () => (node || (node = create())).cloneNode(true); fn.cloneNode = fn; return fn; } function delegateEvents(eventNames, document = window.document) { const e = document[$$EVENTS] || (document[$$EVENTS] = new Set()); for (let i = 0, l = eventNames.length; i < l; i++) { const name = eventNames[i]; if (!e.has(name)) { e.add(name); document.addEventListener(name, eventHandler); } } } function setAttribute(node, name, value) { if (value == null) node.removeAttribute(name);else node.setAttribute(name, value); } function setAttributeNS(node, namespace, name, value) { if (value == null) node.removeAttributeNS(namespace, name);else node.setAttributeNS(namespace, name, value); } function className(node, value) { if (value == null) node.removeAttribute("class");else node.className = value; } function addEventListener(node, name, handler, delegate) { if (delegate) { if (Array.isArray(handler)) { node[`$$${name}`] = handler[0]; node[`$$${name}Data`] = handler[1]; } else node[`$$${name}`] = handler; } else if (Array.isArray(handler)) { const handlerFn = handler[0]; node.addEventListener(name, handler[0] = e => handlerFn.call(node, handler[1], e)); } else node.addEventListener(name, handler); } function classList(node, value, prev = {}) { const classKeys = Object.keys(value || {}), prevKeys = Object.keys(prev); let i, len; for (i = 0, len = prevKeys.length; i < len; i++) { const key = prevKeys[i]; if (!key || key === "undefined" || value[key]) continue; toggleClassKey(node, key, false); delete prev[key]; } for (i = 0, len = classKeys.length; i < len; i++) { const key = classKeys[i], classValue = !!value[key]; if (!key || key === "undefined" || prev[key] === classValue || !classValue) continue; toggleClassKey(node, key, true); prev[key] = classValue; } return prev; } function style(node, value, prev) { if (!value) return prev ? setAttribute(node, "style") : value; const nodeStyle = node.style; if (typeof value === "string") return nodeStyle.cssText = value; typeof prev === "string" && (nodeStyle.cssText = prev = undefined); prev || (prev = {}); value || (value = {}); let v, s; for (s in prev) { value[s] == null && nodeStyle.removeProperty(s); delete prev[s]; } for (s in value) { v = value[s]; if (v !== prev[s]) { nodeStyle.setProperty(s, v); prev[s] = v; } } return prev; } function spread(node, props = {}, isSVG, skipChildren) { const prevProps = {}; if (!skipChildren) { createRenderEffect(() => prevProps.children = insertExpression(node, props.children, prevProps.children)); } createRenderEffect(() => props.ref && props.ref(node)); createRenderEffect(() => assign(node, props, isSVG, true, prevProps, true)); return prevProps; } function insert(parent, accessor, marker, initial) { if (marker !== undefined && !initial) initial = []; if (typeof accessor !== "function") return insertExpression(parent, accessor, initial, marker); createRenderEffect(current => insertExpression(parent, accessor(), current, marker), initial); } function assign(node, props, isSVG, skipChildren, prevProps = {}, skipRef = false) { props || (props = {}); for (const prop in prevProps) { if (!(prop in props)) { if (prop === "children") continue; prevProps[prop] = assignProp(node, prop, null, prevProps[prop], isSVG, skipRef); } } for (const prop in props) { if (prop === "children") { if (!skipChildren) insertExpression(node, props.children); continue; } const value = props[prop]; prevProps[prop] = assignProp(node, prop, value, prevProps[prop], isSVG, skipRef); } } function toPropertyName(name) { return name.toLowerCase().replace(/-([a-z])/g, (_, w) => w.toUpperCase()); } function toggleClassKey(node, key, value) { const classNames = key.trim().split(/\s+/); for (let i = 0, nameLen = classNames.length; i < nameLen; i++) node.classList.toggle(classNames[i], value); } function assignProp(node, prop, value, prev, isSVG, skipRef) { let isCE, isProp, isChildProp, propAlias, forceProp; if (prop === "style") return style(node, value, prev); if (prop === "classList") return classList(node, value, prev); if (value === prev) return prev; if (prop === "ref") { if (!skipRef) value(node); } else if (prop.slice(0, 3) === "on:") { const e = prop.slice(3); prev && node.removeEventListener(e, prev); value && node.addEventListener(e, value); } else if (prop.slice(0, 10) === "oncapture:") { const e = prop.slice(10); prev && node.removeEventListener(e, prev, true); value && node.addEventListener(e, value, true); } else if (prop.slice(0, 2) === "on") { const name = prop.slice(2).toLowerCase(); const delegate = DelegatedEvents.has(name); if (!delegate && prev) { const h = Array.isArray(prev) ? prev[0] : prev; node.removeEventListener(name, h); } if (delegate || value) { addEventListener(node, name, value, delegate); delegate && delegateEvents([name]); } } else if (prop.slice(0, 5) === "attr:") { setAttribute(node, prop.slice(5), value); } else if ((forceProp = prop.slice(0, 5) === "prop:") || (isChildProp = ChildProperties.has(prop)) || !isSVG && ((propAlias = getPropAlias(prop, node.tagName)) || (isProp = Properties.has(prop))) || (isCE = node.nodeName.includes("-"))) { if (forceProp) { prop = prop.slice(5); isProp = true; } if (prop === "class" || prop === "className") className(node, value);else if (isCE && !isProp && !isChildProp) node[toPropertyName(prop)] = value;else node[propAlias || prop] = value; } else { const ns = isSVG && prop.indexOf(":") > -1 && SVGNamespace[prop.split(":")[0]]; if (ns) setAttributeNS(node, ns, prop, value);else setAttribute(node, Aliases[prop] || prop, value); } return value; } function eventHandler(e) { const key = `$$${e.type}`; let node = e.composedPath && e.composedPath()[0] || e.target; if (e.target !== node) { Object.defineProperty(e, "target", { configurable: true, value: node }); } Object.defineProperty(e, "currentTarget", { configurable: true, get() { return node || document; } }); while (node) { const handler = node[key]; if (handler && !node.disabled) { const data = node[`${key}Data`]; data !== undefined ? handler.call(node, data, e) : handler.call(node, e); if (e.cancelBubble) return; } node = node._$host || node.parentNode || node.host; } } function insertExpression(parent, value, current, marker, unwrapArray) { while (typeof current === "function") current = current(); if (value === current) return current; const t = typeof value, multi = marker !== undefined; parent = multi && current[0] && current[0].parentNode || parent; if (t === "string" || t === "number") { if (t === "number") value = value.toString(); if (multi) { let node = current[0]; if (node && node.nodeType === 3) { node.data = value; } else node = document.createTextNode(value); current = cleanChildren(parent, current, marker, node); } else { if (current !== "" && typeof current === "string") { current = parent.firstChild.data = value; } else current = parent.textContent = value; } } else if (value == null || t === "boolean") { current = cleanChildren(parent, current, marker); } else if (t === "function") { createRenderEffect(() => { let v = value(); while (typeof v === "function") v = v(); current = insertExpression(parent, v, current, marker); }); return () => current; } else if (Array.isArray(value)) { const array = []; const currentArray = current && Array.isArray(current); if (normalizeIncomingArray(array, value, current, unwrapArray)) { createRenderEffect(() => current = insertExpression(parent, array, current, marker, true)); return () => current; } if (array.length === 0) { current = cleanChildren(parent, current, marker); if (multi) return current; } else if (currentArray) { if (current.length === 0) { appendNodes(parent, array, marker); } else reconcileArrays(parent, current, array); } else { current && cleanChildren(parent); appendNodes(parent, array); } current = array; } else if (value.nodeType) { if (Array.isArray(current)) { if (multi) return current = cleanChildren(parent, current, marker, value); cleanChildren(parent, current, null, value); } else if (current == null || current === "" || !parent.firstChild) { parent.appendChild(value); } else parent.replaceChild(value, parent.firstChild); current = value; } else console.warn(`Unrecognized value. Skipped inserting`, value); return current; } function normalizeIncomingArray(normalized, array, current, unwrap) { let dynamic = false; for (let i = 0, len = array.length; i < len; i++) { let item = array[i], prev = current && current[i], t; if (item == null || item === true || item === false) ;else if ((t = typeof item) === "object" && item.nodeType) { normalized.push(item); } else if (Array.isArray(item)) { dynamic = normalizeIncomingArray(normalized, item, prev) || dynamic; } else if (t === "function") { if (unwrap) { while (typeof item === "function") item = item(); dynamic = normalizeIncomingArray(normalized, Array.isArray(item) ? item : [item], Array.isArray(prev) ? prev : [prev]) || dynamic; } else { normalized.push(item); dynamic = true; } } else { const value = String(item); if (prev && prev.nodeType === 3 && prev.data === value) normalized.push(prev);else normalized.push(document.createTextNode(value)); } } return dynamic; } function appendNodes(parent, array, marker = null) { for (let i = 0, len = array.length; i < len; i++) parent.insertBefore(array[i], marker); } function cleanChildren(parent, current, marker, replacement) { if (marker === undefined) return parent.textContent = ""; const node = replacement || document.createTextNode(""); if (current.length) { let inserted = false; for (let i = current.length - 1; i >= 0; i--) { const el = current[i]; if (node !== el) { const isParent = el.parentNode === parent; if (!inserted && !i) isParent ? parent.replaceChild(node, el) : parent.insertBefore(node, marker);else isParent && el.remove(); } else inserted = true; } } else parent.insertBefore(node, marker); return [node]; } const SVG_NAMESPACE = "http://www.w3.org/2000/svg"; function createElement(tagName, isSVG = false) { return isSVG ? document.createElementNS(SVG_NAMESPACE, tagName) : document.createElement(tagName); } function Dynamic(props) { const [p, others] = splitProps(props, ["component"]); const cached = createMemo(() => p.component); return createMemo(() => { const component = cached(); switch (typeof component) { case "function": Object.assign(component, { [$DEVCOMP]: true }); return untrack(() => component(others)); case "string": const isSvg = SVGElements.has(component); const el = createElement(component, isSvg); spread(el, others, isSvg); return el; } }); } var throttle = (callback, wait) => { let isThrottled = false, timeoutId, lastArgs; const throttled = (...args) => { lastArgs = args; if (isThrottled) return; isThrottled = true; timeoutId = setTimeout(() => { callback(...lastArgs); isThrottled = false; }, wait); }; const clear = () => { clearTimeout(timeoutId); isThrottled = false; }; if (getOwner()) onCleanup(clear); return Object.assign(throttled, { clear }); }; var access = v => typeof v === "function" && !v.length ? v() : v; var asArray$1 = value => Array.isArray(value) ? value : value ? [value] : []; var tryOnCleanup = onCleanup; function createGMSignal(key, initialValue) { const [signal, setSignal] = createSignal(initialValue); let listener; Promise.resolve().then(() => GMP.addValueChangeListener?.(key, (name, oldValue, newValue, remote) => { if (name === key && (remote === void 0 || remote === true)) read(newValue); })).then(l => listener = l); let effectPaused = false; createEffect(on(signal, () => { if (effectPaused) return; if (signal() == null) { GMP.deleteValue(key); effectPaused = true; setSignal(() => initialValue); effectPaused = false; } else { GMP.setValue(key, signal()); } }, { defer: true })); async function read(newValue) { effectPaused = true; const rawValue = newValue ?? (await GMP.getValue(key)); if (rawValue == null) setSignal(() => initialValue);else setSignal(() => rawValue); effectPaused = false; } const [isReady, setIsReady] = createSignal(false); signal.isReady = isReady; signal.ready = read().then(() => { setIsReady(true); }); onCleanup(() => { if (listener) GMP.removeValueChangeListener?.(listener); }); return [signal, setSignal]; } const [detectionResolution, setDetectionResolution] = createGMSignal("detectionResolution", "M"); const [textDetector, setTextDetector] = createGMSignal("textDetector", "default"); const [translatorService, setTranslatorService] = createGMSignal("translator", "gpt3.5"); const [renderTextOrientation, setRenderTextOrientation] = createGMSignal("renderTextOrientation", "auto"); const [targetLang, setTargetLang] = createGMSignal("targetLang", ""); const [scriptLang, setScriptLang] = createGMSignal("scriptLanguage", ""); const [keepInstances, setKeepInstances] = createGMSignal("keepInstances", "until-reload"); const storageReady = Promise.all([detectionResolution.ready, textDetector.ready, translatorService.ready, renderTextOrientation.ready, targetLang.ready, scriptLang.ready, keepInstances.ready]); var data$1 = { common:{ source:{ "download-image":"正在拉取原图", "download-image-progress":"正在拉取原图({progress})", "download-image-error":"拉取原图出错" }, client:{ submit:"正在提交翻译", "submit-progress":"正在提交翻译({progress})", "submit-final":"等待图片转存", "submit-error":"提交翻译出错", "download-image":"正在下载图片", "download-image-progress":"正在下载图片({progress})", "download-image-error":"下载图片出错", resize:"正在缩放图片", merging:"正在合并图层" }, status:{ "default":"未知状态", pending:"正在等待", "pending-pos":"正在等待,列队还有 {pos} 张图片", downloading:"正在传输图片", preparing:"等待空闲窗口", colorizing:"正在上色", upscaling:"正在放大图片", downscaling:"正在缩小图片", detection:"正在检测文本", ocr:"正在识别文本", textline_merge:"正在整合文本", "mask-generation":"正在生成文本掩码", inpainting:"正在修补图片", translating:"正在翻译文本", rendering:"正在渲染文本", finished:"正在整理结果", saved:"保存结果", saving:"正在保存结果", uploading:"正在传输结果", error:"翻译出错", "error-download":"传输图片失败", "error-upload":"传输结果失败", "error-lang":"你选择的翻译服务不支持你选择的语言", "error-translating":"翻译服务没有返回任何文本", "skip-no-regions":"图片中没有检测到文本区域", "skip-no-text":"图片中没有检测到文本", "error-with-id":"翻译出错 (ID: {id})" }, control:{ translate:"翻译", batch:"翻译全部 ({count})", reset:"还原" }, batch:{ progress:"翻译中 ({count}/{total})", finish:"翻译完成", error:"翻译完成(有失败)" } }, settings:{ title:"Cotrans 图片翻译器设置", "inline-options-title":"设置当前翻译", "detection-resolution":"文本扫描清晰度", "text-detector":"文本扫描器", "text-detector-options":{ "default":"默认" }, translator:"翻译服务", "render-text-orientation":"渲染字体方向", "render-text-orientation-options":{ auto:"跟随原文本", horizontal:"仅限水平", vertical:"仅限垂直" }, "target-language":"翻译语言", "target-language-options":{ auto:"跟随网页语言" }, "script-language":"用户脚本语言", "script-language-options":{ auto:"跟随网页语言" }, reset:"重置所有设置", "detection-resolution-desc":"设置检测图片文本所用的清晰度,小文字适合使用更高的清晰度。", "text-detector-desc":"设置使用的文本扫描器。", "translator-desc":"设置翻译图片所用的翻译服务。", "render-text-orientation-desc":"设置嵌字的文本方向。", "target-language-desc":"设置图片翻译后的语言。", "script-language-desc":"设置此用户脚本的语言。", "translator-options":{ none:"None (删除文字)" }, "keep-instances-options":{ "until-reload":"直到页面刷新", "until-navigate":"直到下次跳转" }, "keep-instances":"保留翻译进度", "keep-instances-desc":"设置翻译进度的保留时间。 翻译进度即图片的翻译状态和翻译结果。 保留更多的翻译进度会占用更多的内存。", "force-retry":"强制重试 (忽略缓存)" }, sponsor:{ text:"制作不易,请考虑赞助我们!" } }; data$1.common; data$1.settings; data$1.sponsor; var data = { common:{ source:{ "download-image":"Downloading original image", "download-image-progress":"Downloading original image ({progress})", "download-image-error":"Error during original image download" }, client:{ submit:"Submitting translation", "submit-progress":"Submitting translation ({progress})", "submit-final":"Waiting for image transpile", "submit-error":"Error during translation submission", "download-image":"Downloading translated image", "download-image-progress":"Downloading translated image ({progress})", "download-image-error":"Error during translated image download", resize:"Resizing image", merging:"Merging layers" }, status:{ "default":"Unknown status", pending:"Pending", "pending-pos":"Pending, {pos} in queue", downloading:"Transferring image", preparing:"Waiting for idle window", colorizing:"Colorizing", upscaling:"Upscaling", downscaling:"Downscaling", detection:"Detecting text", ocr:"Scanning text", textline_merge:"Merging text lines", "mask-generation":"Generating mask", inpainting:"Inpainting", translating:"Translating", rendering:"Rendering", finished:"Finishing", saved:"Saved", saving:"Saving result", uploading:"Transferring result", error:"Error during translation", "error-download":"Image transfer failed", "error-upload":"Result transfer failed", "error-lang":"The target language is not supported by the chosen translator", "error-translating":"Did not get any text back from the text translation service", "skip-no-regions":"No text regions detected in the image", "skip-no-text":"No text detected in the image", "error-with-id":"Error during translation (ID: {id})" }, control:{ translate:"Translate", batch:"Translate all ({count})", reset:"Reset" }, batch:{ progress:"Translating ({count}/{total} finished)", finish:"Translation finished", error:"Translation finished with errors" } }, settings:{ "detection-resolution":"Text detection resolution", "render-text-orientation":"Render text orientation", "render-text-orientation-options":{ auto:"Follow source", horizontal:"Horizontal only", vertical:"Vertical only" }, reset:"Reset Settings", "target-language":"Translate target language", "target-language-options":{ auto:"Follow website" }, "text-detector":"Text detector", "text-detector-options":{ "default":"Default" }, title:"Cotrans Manga Translator Settings", translator:"Translator", "script-language":"Userscript language", "script-language-options":{ auto:"Follow website language" }, "inline-options-title":"Current Settings", "detection-resolution-desc":"The resolution used to scan texts on an image, higher value are better suited for smaller texts.", "script-language-desc":"Language of this userscript.", "render-text-orientation-desc":"Overwrite the orientation of texts rendered in the translated image.", "target-language-desc":"The language that images are translated to.", "text-detector-desc":"The detector used to scan texts in an image.", "translator-desc":"The translate service used to translate texts.", "translator-options":{ none:"None (remove texts)" }, "keep-instances-options":{ "until-reload":"Until page reload", "until-navigate":"Until next navigation" }, "keep-instances":"Keep translation instances", "keep-instances-desc":"How long before a translation instance is disposed. A translation instance includes the translation state of an image, that is, whether the image is translated or not, and the translation result. Keeping more translation instances will result in more memory consumption.", "force-retry":"Force retry (ignore cache)" }, sponsor:{ text:"If you find this script helpful, please consider supporting us!" } }; data.common; data.settings; data.sponsor; const messages = { "zh-CN": data$1, "en-US": data }; function tryMatchLang(lang2) { if (lang2.startsWith("zh")) return "zh-CN"; if (lang2.startsWith("en")) return "en-US"; return "en-US"; } const [realLang, setRealLang] = createSignal(navigator.language); const lang = createMemo(() => scriptLang() || tryMatchLang(realLang())); function t$1(key_, props = {}) { return createMemo(() => { const key = access(key_); const segments = key.split("."); const msg = segments.reduce((obj, k) => obj[k], messages[lang()]) ?? segments.reduce((obj, k) => obj[k], messages["zh-CN"]); if (!msg) return key; return msg.replace(/\{([^}]+)\}/g, (_, k) => String(access(access(props)[k])) ?? ""); }); } let langEL; let langObserver; function changeLangEl(el) { if (langEL === el) return; if (langObserver) langObserver.disconnect(); langObserver = new MutationObserver(mutations => { for (const mutation of mutations) { if (mutation.type === "attributes" && mutation.attributeName === "lang") { const target = mutation.target; if (target.lang) setRealLang(target.lang); break; } } }); langObserver.observe(el, { attributes: true }); langEL = el; setRealLang(el.lang); } function BCP47ToISO639(code) { try { const lo = new Intl.Locale(code); switch (lo.language) { case "zh": { switch (lo.script) { case "Hans": return "CHS"; case "Hant": return "CHT"; } switch (lo.region) { case "CN": return "CHS"; case "HK": case "TW": return "CHT"; } return "CHS"; } case "ja": return "JPN"; case "en": return "ENG"; case "ko": return "KOR"; case "vi": return "VIE"; case "cs": return "CSY"; case "nl": return "NLD"; case "fr": return "FRA"; case "de": return "DEU"; case "hu": return "HUN"; case "it": return "ITA"; case "pl": return "PLK"; case "pt": return "PTB"; case "ro": return "ROM"; case "ru": return "RUS"; case "es": return "ESP"; case "tr": return "TRK"; case "uk": return "UKR"; } return "ENG"; } catch (e) { return "ENG"; } } DelegatedEvents.clear(); function createScopedInstance(cb) { return createRoot(dispose => { const instance = cb(); return { ...instance, dispose }; }); } let currentURL; let translator$3; let settingsInjector$2; async function start(translators, settingsInjectors) { await storageReady; async function onUpdate() { await new Promise(resolve => (queueMicrotask ?? setTimeout)(resolve)); if (currentURL !== location.href) { currentURL = location.href; changeLangEl(document.documentElement); if (translator$3?.canKeep?.(currentURL)) { translator$3.onURLChange?.(currentURL); } else { translator$3?.dispose(); translator$3 = void 0; const url = new URL(location.href); const matched = translators.find(t => t.match(url)); if (matched) translator$3 = createScopedInstance(matched.mount); } if (settingsInjector$2?.canKeep?.(currentURL)) { settingsInjector$2.onURLChange?.(currentURL); } else { settingsInjector$2?.dispose(); settingsInjector$2 = void 0; const url = new URL(location.href); const matched = settingsInjectors.find(t => t.match(url)); if (matched) settingsInjector$2 = createScopedInstance(matched.mount); } } } if (window.onurlchange === null) { window.addEventListener("urlchange", onUpdate); const pushState = history.pushState; window.history.pushState = function () { pushState.apply(this, arguments); if (typeof arguments[2] === "string" && arguments[2].startsWith("#")) onUpdate(); }; } else { const installObserver = new MutationObserver(throttle(onUpdate, 200)); installObserver.observe(document.body, { childList: true, subtree: true }); } onUpdate(); } // src/index.ts var triggerOptions = { equals: false }; var triggerCacheOptions = triggerOptions; var TriggerCache = class { #map; constructor(mapConstructor = Map) { this.#map = new mapConstructor(); } dirty(key) { this.#map.get(key)?.$$(); } track(key) { if (!getListener()) return; let trigger = this.#map.get(key); if (!trigger) { const [$, $$] = createSignal(void 0, triggerCacheOptions); this.#map.set(key, trigger = { $, $$, n: 1 }); } else trigger.n++; onCleanup(() => { if (trigger.n-- === 1) queueMicrotask(() => trigger.n === 0 && this.#map.delete(key)); }); trigger.$(); } }; // src/index.ts var $KEYS = Symbol("track-keys"); var ReactiveMap = class extends Map { #keyTriggers = new TriggerCache(); #valueTriggers = new TriggerCache(); constructor(initial) { super(); if (initial) for (const v of initial) super.set(v[0], v[1]); } // reads has(key) { this.#keyTriggers.track(key); return super.has(key); } get(key) { this.#valueTriggers.track(key); return super.get(key); } get size() { this.#keyTriggers.track($KEYS); return super.size; } keys() { this.#keyTriggers.track($KEYS); return super.keys(); } values() { this.#keyTriggers.track($KEYS); for (const v of super.keys()) this.#valueTriggers.track(v); return super.values(); } entries() { this.#keyTriggers.track($KEYS); for (const v of super.keys()) this.#valueTriggers.track(v); return super.entries(); } // writes set(key, value) { batch(() => { if (super.has(key)) { if (super.get(key) === value) return; } else { this.#keyTriggers.dirty(key); this.#keyTriggers.dirty($KEYS); } this.#valueTriggers.dirty(key); super.set(key, value); }); return this; } delete(key) { const r = super.delete(key); if (r) { batch(() => { this.#keyTriggers.dirty(key); this.#keyTriggers.dirty($KEYS); this.#valueTriggers.dirty(key); }); } return r; } clear() { if (super.size) { batch(() => { for (const v of super.keys()) { this.#keyTriggers.dirty(v); this.#valueTriggers.dirty(v); } super.clear(); this.#keyTriggers.dirty($KEYS); }); } } // callback forEach(callbackfn) { this.#keyTriggers.track($KEYS); super.forEach((value, key) => callbackfn(value, key, this)); } [Symbol.iterator]() { return this.entries(); } }; // src/index.ts function createMutationObserver(initial, b, c) { let defaultOptions, callback; const isSupported = typeof window !== "undefined" && "MutationObserver" in window; if (typeof b === "function") { defaultOptions = {}; callback = b; } else { defaultOptions = b; callback = c; } const instance = isSupported ? new MutationObserver(callback) : void 0; const add = (el, options) => instance?.observe(el, access(options) ?? defaultOptions); const start = () => { asArray$1(access(initial)).forEach(item => { item instanceof Node ? add(item, defaultOptions) : add(item[0], item[1]); }); }; const stop = () => instance?.disconnect(); onMount(start); onCleanup(stop); return [add, { start, stop, instance, isSupported }]; } function toClassName(rule) { return [...rule.v, (rule.i ? '!' : '') + rule.n].join(':'); } function format(rules, seperator = ',') { return rules.map(toClassName).join(seperator); } /** * @internal */ let escape = 'undefined' != typeof CSS && CSS.escape || ( // Simplified: escaping only special characters // Needed for NodeJS and Edge <79 (https://caniuse.com/mdn-api_css_escape) className => className. // Simplifed escape testing only for chars that we know happen to be in tailwind directives replace(/[!"'`*+.,;:\\/<=>?@#$%&^|~()[\]{}]/g, '\\$&'). // If the character is the first character and is in the range [0-9] (2xl, ...) // https://drafts.csswg.org/cssom/#escape-a-character-as-code-point replace(/^\d/, '\\3$& ')); // Based on https://stackoverflow.com/a/52171480 /** * @group Configuration * @param value * @returns */ function hash(value) { // eslint-disable-next-line no-var for (var h = 9, index = value.length; index--;) h = Math.imul(h ^ value.charCodeAt(index), 0x5f356495); return '#' + ((h ^ h >>> 9) >>> 0).toString(36); } /** * @internal * @param screen * @param prefix * @returns */ function mql(screen, prefix = '@media ') { return prefix + asArray(screen).map(screen => { return 'string' == typeof screen && (screen = { min: screen }), screen.raw || Object.keys(screen).map(feature => `(${feature}-width:${screen[feature]})`).join(' and '); }).join(','); } /** * @internal * @param value * @returns */ function asArray(value = []) { return Array.isArray(value) ? value : null == value ? [] : [value]; } /** * @internal * @param value * @returns */ function identity(value) { return value; } /** * @internal */ function noop() {} // no-op // Based on https://github.com/kripod/otion // License MIT // export const enum Shifts { // darkMode = 30, // layer = 27, // screens = 26, // responsive = 22, // atRules = 18, // variants = 0, // } let Layer = { /** * 1. `default` (public) */ d: /* efaults */0, /* Shifts.layer */ /** * 2. `base` (public) — for things like reset rules or default styles applied to plain HTML elements. */b: /* ase */134217728, /* Shifts.layer */ /** * 3. `components` (public, used by `style()`) — is for class-based styles that you want to be able to override with utilities. */c: /* omponents */268435456, /* Shifts.layer */ // reserved for style(): // - props: 0b011 // - when: 0b100 /** * 6. `aliases` (public, used by `apply()`) — `~(...)` */a: /* liases */671088640, /* Shifts.layer */ /** * 6. `utilities` (public) — for small, single-purpose classes */u: /* tilities */805306368, /* Shifts.layer */ /** * 7. `overrides` (public, used by `css()`) */o: /* verrides */939524096 }; /* To set a bit: n |= mask; To clear a bit: n &= ~mask; To test if a bit is set: (n & mask) Bit shifts for the primary bits: | bits | trait | shift | | ---- | ------------------------------------------------------- | ----- | | 1 | dark mode | 30 | | 3 | layer: preflight, global, components, utilities, css | 27 | | 1 | screens: is this a responsive variation of a rule | 26 | | 4 | responsive based on min-width, max-width or width | 22 | | 4 | at-rules | 18 | | 18 | pseudo and group variants | 0 | Layer: 0 - 7: 3 bits - defaults: 0 << 27 - base: 1 << 27 - components: 2 << 27 - variants: 3 << 27 - joints: 4 << 27 - aliases: 5 << 27 - utilities: 6 << 27 - overrides: 7 << 27 These are calculated by serialize and added afterwards: | bits | trait | | ---- | ----------------------------------- | | 4 | number of selectors (descending) | | 4 | number of declarations (descending) | | 4 | greatest precedence of properties | These are added by shifting the primary bits using multiplication as js only supports bit shift up to 32 bits. */ // Colon and dash count of string (ascending) function seperatorPrecedence(string) { return string.match(/[-=:;]/g)?.length || 0; } function atRulePrecedence(css) { // 0 - 15: 4 bits (max 144rem or 2304px) // rem -> bit // <20 -> 0 (<320px) // 20 -> 1 (320px) // 24 -> 2 (384px) // 28 -> 3 (448px) // 32 -> 4 (512px) // 36 -> 5 (576px) // 42 -> 6 (672px) // 48 -> 7 (768px) // 56 -> 8 (896px) // 64 -> 9 (1024px) // 72 -> 10 (1152px) // 80 -> 11 (1280px) // 96 -> 12 (1536px) // 112 -> 13 (1792px) // 128 -> 14 (2048px) // 144 -> 15 (2304px) // https://www.dcode.fr/function-equation-finder return Math.min(/(?:^|width[^\d]+)(\d+(?:.\d+)?)(p)?/.test(css) ? Math.max(0, 29.63 * (+RegExp.$1 / (RegExp.$2 ? 15 : 1)) ** 0.137 - 43) : 0, 15) << 22 | /* Shifts.responsive */Math.min(seperatorPrecedence(css), 15) << 18; } /* Shifts.atRules */ // Pesudo variant presedence // Chars 3 - 8: Uniquely identifies a pseudo selector // represented as a bit set for each relevant value // 18 bits: one for each variant plus one for unknown variants // // ':group-*' variants are normalized to their native pseudo class (':group-hover' -> ':hover') // as they already have a higher selector presedence due to the add '.group' ('.group:hover .group-hover:...') // Sources: // - https://bitsofco.de/when-do-the-hover-focus-and-active-pseudo-classes-apply/#orderofstyleshoverthenfocusthenactive // - https://developer.mozilla.org/docs/Web/CSS/:active#Active_links // - https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js#L931 let PRECEDENCES_BY_PSEUDO_CLASS = [/* fi */'rst-c', /* hild: 0 */ /* la */'st-ch', /* ild: 1 */ // even and odd use: nth-child /* nt */'h-chi', /* ld: 2 */ /* an */'y-lin', /* k: 3 */ /* li */'nk', /* : 4 */ /* vi */'sited', /* : 5 */ /* ch */'ecked', /* : 6 */ /* em */'pty', /* : 7 */ /* re */'ad-on', /* ly: 8 */ /* fo */'cus-w', /* ithin : 9 */ /* ho */'ver', /* : 10 */ /* fo */'cus', /* : 11 */ /* fo */'cus-v', /* isible : 12 */ /* ac */'tive', /* : 13 */ /* di */'sable', /* d : 14 */ /* op */'tiona', /* l: 15 */ /* re */'quire']; /** The name to use for `&` expansion in selectors. Maybe empty for at-rules like `@import`, `@font-face`, `@media`, ... */ /** The calculated precedence taking all variants into account. */ /** The rulesets (selectors and at-rules). expanded variants `@media ...`, `@supports ...`, `&:focus`, `.dark &` */ /** Is this rule `!important` eg something like `!underline` or `!bg-red-500` or `!red-500` */ function convert({ n: name, i: important, v: variants = [] }, context, precedence, conditions) { name && (name = toClassName({ n: name, i: important, v: variants })); conditions = [...asArray(conditions)]; for (let variant of variants) { let screen = context.theme('screens', variant); for (let condition of asArray(screen && mql(screen) || context.v(variant))) { var /* d: 16 */selector; conditions.push(condition); precedence |= screen ? 67108864 | /* Shifts.screens */atRulePrecedence(condition) : 'dark' == variant ? 1073741824 : /* Shifts.darkMode */'@' == condition[0] ? atRulePrecedence(condition) : (selector = condition, // use first found pseudo-class 1 << ~(/:([a-z-]+)/.test(selector) && ~PRECEDENCES_BY_PSEUDO_CLASS.indexOf(RegExp.$1.slice(2, 7)) || -18)); } } return { n: name, p: precedence, r: conditions, i: important }; } let registry = new Map(); function stringify$1(rule) { if (rule.d) { let groups = [], selector = replaceEach( // merge all conditions into a selector string rule.r.reduce((selector, condition) => { return '@' == condition[0] ? (groups.push(condition), selector) : // Go over the selector and replace the matching multiple selectors if any condition ? replaceEach(selector, selectorPart => replaceEach(condition, // If the current condition has a nested selector replace it conditionPart => { let mergeMatch = /(:merge\(.+?\))(:[a-z-]+|\\[.+])/.exec(conditionPart); if (mergeMatch) { let selectorIndex = selectorPart.indexOf(mergeMatch[1]); return ~selectorIndex ? // [':merge(.group):hover .rule', ':merge(.group):focus &'] -> ':merge(.group):focus:hover .rule' // ':merge(.group)' + ':focus' + ':hover .rule' selectorPart.slice(0, selectorIndex) + mergeMatch[0] + selectorPart.slice(selectorIndex + mergeMatch[1].length) : // [':merge(.peer):focus~&', ':merge(.group):hover &'] -> ':merge(.peer):focus~:merge(.group):hover &' replaceReference(selectorPart, conditionPart); } // Return the current selector with the key matching multiple selectors if any return replaceReference(conditionPart, selectorPart); })) : selector; }, '&'), // replace '&' with rule name or an empty string selectorPart => replaceReference(selectorPart, rule.n ? '.' + escape(rule.n) : '')); return selector && groups.push(selector.replace(/:merge\((.+?)\)/g, '$1')), groups.reduceRight((body, grouping) => grouping + '{' + body + '}', rule.d); } } function replaceEach(selector, iteratee) { return selector.replace(/ *((?:\(.+?\)|\[.+?\]|[^,])+) *(,|$)/g, (_, selectorPart, comma) => iteratee(selectorPart) + comma); } function replaceReference(selector, reference) { return selector.replace(/&/g, reference); } let collator = new Intl.Collator('en', { numeric: true }); /** The calculated precedence taking all variants into account. */ /* The precedence of the properties within {@link d}. */ /** The name to use for `&` expansion in selectors. Maybe empty for at-rules like `@import`, `@font-face`, `@media`, ... */ /** * Find the array index of where to add an element to keep it sorted. * * @returns The insertion index */ function sortedInsertionIndex(array, element) { // Find position using binary search // eslint-disable-next-line no-var for (var low = 0, high = array.length; low < high;) { let pivot = high + low >> 1; 0 >= compareTwindRules(array[pivot], element) ? low = pivot + 1 : high = pivot; } return high; } function compareTwindRules(a, b) { // base and overrides (css) layers are kept in order they are declared let layer = a.p & Layer.o; return layer == (b.p & Layer.o) && (layer == Layer.b || layer == Layer.o) ? 0 : a.p - b.p || a.o - b.o || collator.compare(byModifier(a.n), byModifier(b.n)) || collator.compare(byName(a.n), byName(b.n)); } function byModifier(s) { return (s || '').split(/:/).pop().split('/').pop() || '\x00'; } function byName(s) { return (s || '').replace(/\W/g, c => String.fromCharCode(127 + c.charCodeAt(0))) + '\x00'; } function parseColorComponent(chars, factor) { return Math.round(parseInt(chars, 16) * factor); } /** * @internal * @param color * @param options * @returns */ function toColorValue(color, options = {}) { if ('function' == typeof color) return color(options); let { opacityValue = '1', opacityVariable } = options, opacity = opacityVariable ? `var(${opacityVariable})` : opacityValue; if (color.includes('')) return color.replace('', opacity); // rgb hex: #0123 and #001122 if ('#' == color[0] && (4 == color.length || 7 == color.length)) { let size = (color.length - 1) / 3, factor = [17, 1, 0.062272][size - 1]; return `rgba(${[parseColorComponent(color.substr(1, size), factor), parseColorComponent(color.substr(1 + size, size), factor), parseColorComponent(color.substr(1 + 2 * size, size), factor), opacity]})`; } return '1' == opacity ? color : '0' == opacity ? '#0000' : // convert rgb and hsl to alpha variant color.replace(/^(rgb|hsl)(\([^)]+)\)$/, `$1a$2,${opacity})`); } function serialize(style, rule, context, precedence, conditions = []) { return function serialize$(style, { n: name, p: precedence, r: conditions = [], i: important }, context) { let rules = [], // The generated declaration block eg body of the css rule declarations = '', // This ensures that 'border-top-width' has a higher precedence than 'border-top' maxPropertyPrecedence = 0, // More specific utilities have less declarations and a higher precedence numberOfDeclarations = 0; for (let key in style || {}) { var layer, // https://github.com/kripod/otion/blob/main/packages/otion/src/propertyMatchers.ts // "+1": [ // /* ^border-.*(w|c|sty) */ // "border-.*(width,color,style)", // /* ^[tlbr].{2,4}m?$ */ // "top", // "left", // "bottom", // "right", // /* ^c.{7}$ */ // "continue", // /* ^c.{8}$ */ // "container", // ], // "-1": [ // /* ^[fl].{5}l */ // "flex-flow", // "line-clamp", // /* ^g.{8}$ */ // "grid-area", // /* ^pl */ // "place-content", // "place-items", // "place-self", // ], // group: 1 => +1 // group: 2 => -1 // 0 - 15 => 4 bits // Ignore vendor prefixed and custom properties property; let value = style[key]; if ('@' == key[0]) { // at rules: https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule if (!value) continue; // @apply ...; if ('a' == key[1]) { rules.push(...translateWith(name, precedence, parse('' + value), context, precedence, conditions, important, true)); continue; } // @layer if ('l' == key[1]) { for (let css of asArray(value)) rules.push(...serialize$(css, { n: name, p: (layer = Layer[key[7]], // Set layer (first reset, than set) precedence & ~Layer.o | layer), r: 'd' == key[7] ? [] : conditions, i: important }, context)); continue; } // @import if ('i' == key[1]) { rules.push(...asArray(value).map(value => ({ // before all layers p: -1, o: 0, r: [], d: key + ' ' + value }))); continue; } // @keyframes if ('k' == key[1]) { // Use defaults layer rules.push({ p: Layer.d, o: 0, r: [key], d: serialize$(value, { p: Layer.d }, context).map(stringify$1).join('') }); continue; } // @font-face // TODO @font-feature-values if ('f' == key[1]) { // Use defaults layer rules.push(...asArray(value).map(value => ({ p: Layer.d, o: 0, r: [key], d: serialize$(value, { p: Layer.d }, context).map(stringify$1).join('') }))); continue; } } // -> All other are handled below; same as selector // @media // @supports // selector if ('object' != typeof value || Array.isArray(value)) { if ('label' == key && value) name = value + hash(JSON.stringify([precedence, important, style]));else if (value || 0 === value) { // property -> hyphenate key = key.replace(/[A-Z]/g, _ => '-' + _.toLowerCase()); // Update precedence numberOfDeclarations += 1; maxPropertyPrecedence = Math.max(maxPropertyPrecedence, '-' == (property = key)[0] ? 0 : seperatorPrecedence(property) + (/^(?:(border-(?!w|c|sty)|[tlbr].{2,4}m?$|c.{7,8}$)|([fl].{5}l|g.{8}$|pl))/.test(property) ? +!!RegExp.$1 || /* +1 */-!!RegExp.$2 : /* -1 */0) + 1); declarations += (declarations ? ';' : '') + asArray(value).map(value => context.s(key, // support theme(...) function in values // calc(100vh - theme('spacing.12')) resolveThemeFunction('' + value, context.theme) + (important ? ' !important' : ''))).join(';'); } } else // at-rule or non-global selector if ('@' == key[0] || key.includes('&')) { let rulePrecedence = precedence; if ('@' == key[0]) { // Handle `@media screen(sm)` and `@media (screen(sm) or ...)` key = key.replace(/\bscreen\(([^)]+)\)/g, (_, screenKey) => { let screen = context.theme('screens', screenKey); return screen ? (rulePrecedence |= 67108864, /* Shifts.screens */mql(screen, '')) : _; }); rulePrecedence |= atRulePrecedence(key); } rules.push(...serialize$(value, { n: name, p: rulePrecedence, r: [...conditions, key], i: important }, context)); } else // global selector rules.push(...serialize$(value, { p: precedence, r: [...conditions, key] }, context)); } return ( // PERF: prevent unshift using `rules = [{}]` above and then `rules[0] = {...}` rules.unshift({ n: name, p: precedence, o: // number of declarations (descending) Math.max(0, 15 - numberOfDeclarations) + // greatest precedence of properties // if there is no property precedence this is most likely a custom property only declaration // these have the highest precedence 1.5 * Math.min(maxPropertyPrecedence || 15, 15), r: conditions, // stringified declarations d: declarations }), rules.sort(compareTwindRules) ); }(style, convert(rule, context, precedence, conditions), context); } function resolveThemeFunction(value, theme) { // support theme(...) function in values // calc(100vh - theme('spacing.12')) // theme('borderColor.DEFAULT', 'currentColor') // PERF: check for theme before running the regexp // if (value.includes('theme')) { return value.replace(/theme\((["'`])?(.+?)\1(?:\s*,\s*(["'`])?(.+?)\3)?\)/g, (_, __, key, ___, defaultValue = '') => { let value = theme(key, defaultValue); return 'function' == typeof value && /color|fill|stroke/i.test(key) ? toColorValue(value) : '' + asArray(value).filter(v => Object(v) !== v); }); } // } // return value function merge(rules, name) { let current; // merge: // - same conditions // - replace name with hash of name + condititions + declarations // - precedence: // - combine bits or use max precendence // - set layer bit to merged let result = []; for (let rule of rules) // only merge rules with declarations and names (eg no global rules) if (rule.d && rule.n) { if (current?.p == rule.p && '' + current.r == '' + rule.r) { current.c = [current.c, rule.c].filter(Boolean).join(' '); current.d = current.d + ';' + rule.d; } else // only set name for named rules eg not for global or className propagation rules result.push(current = { ...rule, n: rule.n && name }); } else result.push({ ...rule, n: rule.n && name }); return result; } function translate(rules, context, precedence = Layer.u, conditions, important) { // Sorted by precedence let result = []; for (let rule of rules) for (let cssRule of function (rule, context, precedence, conditions, important) { rule = { ...rule, i: rule.i || important }; let resolved = function (rule, context) { let factory = registry.get(rule.n); return factory ? factory(rule, context) : context.r(rule.n, 'dark' == rule.v[0]); }(rule, context); return resolved ? // a list of class names 'string' == typeof resolved ? (({ r: conditions, p: precedence } = convert(rule, context, precedence, conditions)), merge(translate(parse(resolved), context, precedence, conditions, rule.i), rule.n)) : Array.isArray(resolved) ? resolved.map(rule => { var /* Shifts.layer */ /* To have a predictable styling the styles must be ordered. This order is represented by a precedence number. The lower values are inserted before higher values. Meaning higher precedence styles overwrite lower precedence styles. Each rule has some traits that are put into a bit set which form the precedence: | bits | trait | | ---- | ---------------------------------------------------- | | 1 | dark mode | | 2 | layer: preflight, global, components, utilities, css | | 1 | screens: is this a responsive variation of a rule | | 5 | responsive based on min-width | | 4 | at-rules | | 18 | pseudo and group variants | | 4 | number of declarations (descending) | | 4 | greatest precedence of properties | **Dark Mode: 1 bit** Flag for dark mode rules. **Layer: 3 bits** - defaults = 0: The preflight styles and any base styles registered by plugins. - base = 1: The global styles registered by plugins. - components = 2 - variants = 3 - compounds = 4 - aliases = 5 - utilities = 6: Utility classes and any utility classes registered by plugins. - css = 7: Styles generated by css **Screens: 1 bit** Flag for screen variants. They may not always have a `min-width` to be detected by _Responsive_ below. **Responsive: 4 bits** Based on extracted `min-width` value: - 576px -> 3 - 1536px -> 10 - 36rem -> 3 - 96rem -> 9 **At-Rules: 4 bits** Based on the count of special chars (`-:,`) within the at-rule. **Pseudo and group variants: 18 bits** Ensures predictable order of pseudo classes. - https://bitsofco.de/when-do-the-hover-focus-and-active-pseudo-classes-apply/#orderofstyleshoverthenfocusthenactive - https://developer.mozilla.org/docs/Web/CSS/:active#Active_links - https://github.com/tailwindlabs/tailwindcss/blob/master/stubs/defaultConfig.stub.js#L718 **Number of declarations (descending): 4 bits** Allows single declaration styles to overwrite styles from multi declaration styles. **Greatest precedence of properties: 4 bits** Ensure shorthand properties are inserted before longhand properties; eg longhand override shorthand */precedence1, layer; return { o: 0, ...rule, r: [...asArray(conditions), ...asArray(rule.r)], p: (precedence1 = precedence, layer = rule.p ?? precedence, precedence1 & ~Layer.o | layer) }; }) : serialize(resolved, rule, context, precedence, conditions) : // propagate className as is [{ c: toClassName(rule), p: 0, o: 0, r: [] }]; }(rule, context, precedence, conditions, important)) result.splice(sortedInsertionIndex(result, cssRule), 0, cssRule); return result; } function translateWith(name, layer, rules, context, precedence, conditions, important, useOrderOfRules) { return merge((useOrderOfRules ? rules.flatMap(rule => translate([rule], context, precedence, conditions, important)) : translate(rules, context, precedence, conditions, important)).map(rule => { return ( // do not move defaults // move only rules with a name unless they are in the base layer rule.p & Layer.o && (rule.n || layer == Layer.b) ? { ...rule, p: rule.p & ~Layer.o | layer, o: 0 } : rule ); }), name); } function define(className, layer, rules, useOrderOfRules) { var factory; return factory = (rule, context) => { let { n: name, p: precedence, r: conditions, i: important } = convert(rule, context, layer); return rules && translateWith(name, layer, rules, context, precedence, conditions, important, useOrderOfRules); }, registry.set(className, factory), className; } /** * The utility name including `-` if set, but without `!` and variants */ /** * All variants without trailing colon: `hover`, `after:`, `[...]` */ /** * Something like `!underline` or `!bg-red-500` or `!red-500` */ function createRule(active, current, loc) { if ('(' != active[active.length - 1]) { let variants = [], important = false, negated = false, name = ''; for (let value of active) if (!('(' == value || /[~@]$/.test(value))) { if ('!' == value[0]) { value = value.slice(1); important = !important; } if (value.endsWith(':')) { variants['dark:' == value ? 'unshift' : 'push'](value.slice(0, -1)); continue; } if ('-' == value[0]) { value = value.slice(1); negated = !negated; } value.endsWith('-') && (value = value.slice(0, -1)); value && '&' != value && (name += (name && '-') + value); } if (name) { negated && (name = '-' + name); current[0].push({ n: name, v: variants.filter(uniq), i: important }); } } } function uniq(value, index, values) { return values.indexOf(value) == index; } let cache = new Map(); /** * @internal * @param token * @returns */ function parse(token) { let parsed = cache.get(token); if (!parsed) { // Stack of active groupings (`(`), variants, or nested (`~` or `@`) let active = [], // Stack of current rule list to put new rules in // the first `0` element is the current list current = [[]], startIndex = 0, skip = 0, comment = null, position = 0, // eslint-disable-next-line no-inner-declarations commit = (isRule, endOffset = 0) => { if (startIndex != position) { active.push(token.slice(startIndex, position + endOffset)); isRule && createRule(active, current); } startIndex = position + 1; }; for (; position < token.length; position++) { let char = token[position]; if (skip) '\\' != token[position - 1] && (skip += +('[' == char) || -(']' == char));else if ('[' == char) // start to skip skip += 1;else if (comment) { if ('\\' != token[position - 1] && comment.test(token.slice(position))) { comment = null; startIndex = position + RegExp.lastMatch.length; } } else if ('/' == char && '\\' != token[position - 1] && ('*' == token[position + 1] || '/' == token[position + 1])) // multiline or single line comment comment = '*' == token[position + 1] ? /^\*\// : /^[\r\n]/;else if ('(' == char) { // hover:(...) or utilitity-(...) commit(); active.push(char); } else if (':' == char) ':' != token[position + 1] && commit(false, 1);else if (/[\s,)]/.test(char)) { // whitespace, comma or closing brace commit(true); let lastGroup = active.lastIndexOf('('); if (')' == char) { // Close nested block let nested = active[lastGroup - 1]; if (/[~@]$/.test(nested)) { let rules = current.shift(); active.length = lastGroup; // remove variants that are already applied through active createRule([...active, '#'], current); let { v } = current[0].pop(); for (let rule of rules) // if a rule has dark we need to splice after the first entry eg dark rule.v.splice(+('dark' == rule.v[0]) - +('dark' == v[0]), v.length); createRule([...active, define( // named nested nested.length > 1 ? nested.slice(0, -1) + hash(JSON.stringify([nested, rules])) : nested + '(' + format(rules) + ')', Layer.a, rules, /@$/.test(nested))], current); } lastGroup = active.lastIndexOf('(', lastGroup - 1); } active.length = lastGroup + 1; } else /[~@]/.test(char) && '(' == token[position + 1] && // start nested block // ~(...) or button~(...) // @(...) or button@(...) current.unshift([]); } // Consume remaining stack commit(true); cache.set(token, parsed = current[0]); } return parsed; } /** The found theme value */ // indirection wrapper to remove autocomplete functions from production bundles /** * @group Configuration * @param pattern */ /** * @group Configuration * @param pattern * @param resolver */ /** * @group Configuration * @param pattern * @param resolve */ // eslint-disable-next-line @typescript-eslint/ban-types /** * @group Configuration * @param pattern * @param resolve * @param convert */ function match(pattern, // eslint-disable-next-line @typescript-eslint/ban-types resolve, convert) { return [pattern, fromMatch(resolve, convert)]; } /** * @group Configuration * @internal * @deprecated Use {@link match} instead. */ /** * @group Configuration * @internal * @deprecated Use {@link match} instead. */ /** * @group Configuration * @internal * @deprecated Use {@link match} instead. */ /** * @group Configuration * @internal * @deprecated Use {@link match} instead. */ function fromMatch(resolve, convert) { return 'function' == typeof resolve ? resolve : 'string' == typeof resolve && /^[\w-]+$/.test(resolve) ? // a CSS property alias (match, context) => ({ [resolve]: convert ? convert(match, context) : maybeNegate(match, 1) }) : match => // CSSObject, shortcut or apply resolve || { [match[1]]: maybeNegate(match, 2) }; } function maybeNegate(match, offset, value = match.slice(offset).find(Boolean) || match.$$ || match.input) { return '-' == match.input[0] ? `calc(${value} * -1)` : value; } /** * @group Configuration * @param pattern * @param section * @param resolve * @param convert * @returns */ function matchTheme(pattern, /** Theme section to use (default: `$1` — The first matched group) */section, /** The css property (default: value of {@link section}) */resolve, convert) { return [pattern, fromTheme(section, resolve, convert)]; } /** * @group Configuration * @internal * @deprecated Use {@link matchTheme} instead. * @param section * @param resolve * @param convert * @returns */ function fromTheme( /** Theme section to use (default: `$1` — The first matched group) */section, /** The css property (default: value of {@link section}) */resolve, convert) { let factory = 'string' == typeof resolve ? (match, context) => ({ [resolve]: convert ? convert(match, context) : match._ }) : resolve || (({ 1: $1, _ }, context, section) => ({ [$1 || section]: _ })); return (match, context) => { let themeSection = camelize(section || match[1]), value = context.theme(themeSection, match.$$) ?? arbitrary(match.$$, themeSection, context); if (null != value) return match._ = maybeNegate(match, 0, value), factory(match, context, themeSection); }; } /** Theme section to use (default: `$0.replace('-', 'Color')` — The matched string with `Color` appended) */ /** The css property (default: value of {@link section}) */ /** `--tw-${$0}opacity` -> '--tw-text-opacity' */ /** `section.replace('Color', 'Opacity')` -> 'textOpacity' */ /** * @group Configuration * @param pattern * @param options * @param resolve * @returns */ function matchColor(pattern, options = {}, resolve) { return [pattern, colorFromTheme(options, resolve)]; } /** * @group Configuration * @internal * @deprecated Use {@link matchColor} instead. * @param options * @param resolve * @returns */ function colorFromTheme(options = {}, resolve) { return (match, context) => { // text- -> textColor // ring-offset(?:-|$) -> ringOffsetColor let { section = camelize(match[0]).replace('-', '') + 'Color' } = options, // extract color and opacity // rose-500 -> ['rose-500'] // [hsl(0_100%_/_50%)] -> ['[hsl(0_100%_/_50%)]'] // indigo-500/100 -> ['indigo-500', '100'] // [hsl(0_100%_/_50%)]/[.25] -> ['[hsl(0_100%_/_50%)]', '[.25]'] [colorMatch, opacityMatch] = parseValue(match.$$); if (!colorMatch) return; let colorValue = context.theme(section, colorMatch) || arbitrary(colorMatch, section, context); if (!colorValue || 'object' == typeof colorValue) return; let { // text- -> --tw-text-opacity // ring-offset(?:-|$) -> --tw-ring-offset-opacity // TODO move this default into preset-tailwind? opacityVariable = `--tw-${match[0].replace(/-$/, '')}-opacity`, opacitySection = section.replace('Color', 'Opacity'), property = section, selector } = options, opacityValue = context.theme(opacitySection, opacityMatch || 'DEFAULT') || opacityMatch && arbitrary(opacityMatch, opacitySection, context), // if (typeof color != 'string') { // console.warn(`Invalid color ${colorMatch} (from ${match.input}):`, color) // return // } create = resolve || (({ _ }) => { let properties = toCSS(property, _); return selector ? { [selector]: properties } : properties; }); match._ = { value: toColorValue(colorValue, { opacityVariable: opacityVariable || void 0, opacityValue: opacityValue || void 0 }), color: options => toColorValue(colorValue, options), opacityVariable: opacityVariable || void 0, opacityValue: opacityValue || void 0 }; let properties = create(match, context); // auto support dark mode colors if (!match.dark) { let darkColorValue = context.d(section, colorMatch, colorValue); if (darkColorValue && darkColorValue !== colorValue) { match._ = { value: toColorValue(darkColorValue, { opacityVariable: opacityVariable || void 0, opacityValue: opacityValue || '1' }), color: options => toColorValue(darkColorValue, options), opacityVariable: opacityVariable || void 0, opacityValue: opacityValue || void 0 }; properties = { '&': properties, [context.v('dark')]: create(match, context) }; } } return properties; }; } /** * @internal * @param input */ function parseValue(input) { // extract color and opacity // rose-500 -> ['rose-500'] // [hsl(0_100%_/_50%)] -> ['[hsl(0_100%_/_50%)]'] // indigo-500/100 -> ['indigo-500', '100'] // [hsl(0_100%_/_50%)]/[.25] -> ['[hsl(0_100%_/_50%)]', '[.25]'] return (input.match(/^(\[[^\]]+]|[^/]+?)(?:\/(.+))?$/) || []).slice(1); } /** * @internal * @param property * @param value * @returns */ function toCSS(property, value) { let properties = {}; if ('string' == typeof value) properties[property] = value;else { value.opacityVariable && value.value.includes(value.opacityVariable) && (properties[value.opacityVariable] = value.opacityValue || '1'); properties[property] = value.value; } return properties; } /** * @internal * @param value * @param section * @param context * @returns */ function arbitrary(value, section, context) { if ('[' == value[0] && ']' == value.slice(-1)) { value = normalize(resolveThemeFunction(value.slice(1, -1), context.theme)); if (!section) return value; if ( // Respect type hints from the user on ambiguous arbitrary values - https://tailwindcss.com/docs/adding-custom-styles#resolving-ambiguities !( // If this is a color section and the value is a hex color, color function or color name /color|fill|stroke/i.test(section) && !(/^color:/.test(value) || /^(#|((hsl|rgb)a?|hwb|lab|lch|color)\(|[a-z]+$)/.test(value)) || // url(, [a-z]-gradient(, image(, cross-fade(, image-set( /image/i.test(section) && !(/^image:/.test(value) || /^[a-z-]+\(/.test(value)) || // font-* // - fontWeight (type: ['lookup', 'number', 'any']) // - fontFamily (type: ['lookup', 'generic-name', 'family-name']) /weight/i.test(section) && !(/^(number|any):/.test(value) || /^\d+$/.test(value)) || // bg-* // - backgroundPosition (type: ['lookup', ['position', { preferOnConflict: true }]]) // - backgroundSize (type: ['lookup', 'length', 'percentage', 'size']) /position/i.test(section) && /^(length|size):/.test(value))) // remove arbitrary type prefix — we do not need it but user may use it // https://github.com/tailwindlabs/tailwindcss/blob/master/src/util/dataTypes.js // url, number, percentage, length, line-width, shadow, color, image, gradient, position, family-name, lookup, any, generic-name, absolute-size, relative-size return value.replace(/^[a-z-]+:/, ''); } } function camelize(value) { return value.replace(/-./g, x => x[1].toUpperCase()); } /** * @internal * @param value * @returns */ function normalize(value) { return ( // Keep raw strings if it starts with `url(` value.includes('url(') ? value.replace(/(.*?)(url\(.*?\))(.*?)/g, (_, before = '', url, after = '') => normalize(before) + url + normalize(after)) : value. // Convert `_` to ` `, except for escaped underscores `\_` replace(/(^|[^\\])_+/g, (fullMatch, characterBefore) => characterBefore + ' '.repeat(fullMatch.length - characterBefore.length)).replace(/\\_/g, '_'). // Add spaces around operators inside math functions like calc() that do not follow an operator // or '('. replace(/(calc|min|max|clamp)\(.+\)/g, match => match.replace(/(-?\d*\.?\d(?!\b-.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, '$1 $2 ')) ); } /** * @group Configuration * @param param0 * @returns */ function defineConfig({ presets = [], ...userConfig }) { // most user config values go first to have precendence over preset config // only `preflight` and `theme` are applied as last preset to override all presets let config = { darkMode: void 0, darkColor: void 0, preflight: false !== userConfig.preflight && [], theme: {}, variants: asArray(userConfig.variants), rules: asArray(userConfig.rules), ignorelist: asArray(userConfig.ignorelist), hash: void 0, stringify: (property, value) => property + ':' + value, finalize: [] }; for (let preset of asArray([...presets, { darkMode: userConfig.darkMode, darkColor: userConfig.darkColor, preflight: false !== userConfig.preflight && asArray(userConfig.preflight), theme: userConfig.theme, hash: userConfig.hash, stringify: userConfig.stringify, finalize: userConfig.finalize }])) { let { preflight, darkMode = config.darkMode, darkColor = config.darkColor, theme, variants, rules, ignorelist, hash = config.hash, stringify = config.stringify, finalize } = 'function' == typeof preset ? preset(config) : preset; config = { // values defined by user or previous presets take precedence preflight: false !== config.preflight && false !== preflight && [...config.preflight, ...asArray(preflight)], darkMode, darkColor, theme: { ...config.theme, ...theme, extend: { ...config.theme.extend, ...theme?.extend } }, variants: [...config.variants, ...asArray(variants)], rules: [...config.rules, ...asArray(rules)], ignorelist: [...config.ignorelist, ...asArray(ignorelist)], hash, stringify, finalize: [...config.finalize, ...asArray(finalize)] }; } return config; } function find(value, list, cache, getResolver, context, isDark) { for (let item of list) { let resolver = cache.get(item); resolver || cache.set(item, resolver = getResolver(item)); let resolved = resolver(value, context, isDark); if (resolved) return resolved; } } function getVariantResolver(variant) { var resolve; return createResolve(variant[0], 'function' == typeof (resolve = variant[1]) ? resolve : () => resolve); } function getRuleResolver(rule) { var resolve, convert; return Array.isArray(rule) ? createResolve(rule[0], fromMatch(rule[1], rule[2])) : createResolve(rule, fromMatch(resolve, convert)); } function createResolve(patterns, resolve) { return createRegExpExecutor(patterns, (value, condition, context, isDark) => { let match = condition.exec(value); if (match) return ( // MATCH.$_ = value match.$$ = value.slice(match[0].length), match.dark = isDark, resolve(match, context) ); }); } function createRegExpExecutor(patterns, run) { let conditions = asArray(patterns).map(toCondition); return (value, context, isDark) => { for (let condition of conditions) { let result = run(value, condition, context, isDark); if (result) return result; } }; } function toCondition(value) { // "visible" -> /^visible$/ // "(float)-(left|right|none)" -> /^(float)-(left|right|none)$/ // "auto-rows-" -> /^auto-rows-/ // "gap(-|$)" -> /^gap(-|$)/ return 'string' == typeof value ? RegExp('^' + value + (value.includes('$') || '-' == value.slice(-1) ? '' : '$')) : value; } /** * @group Runtime * @param config * @param sheet */ function twind(userConfig, sheet) { let config = defineConfig(userConfig), context = function ({ theme, darkMode, darkColor = noop, variants, rules, hash: hash$1, stringify, ignorelist, finalize }) { // Used to cache resolved rule values let variantCache = new Map(), // lazy created resolve functions variantResolvers = new Map(), // Used to cache resolved rule values ruleCache = new Map(), // lazy created resolve functions ruleResolvers = new Map(), ignored = createRegExpExecutor(ignorelist, (value, condition) => condition.test(value)); // add dark as last variant to allow user to override it // we can modify variants as it has been passed through defineConfig which already made a copy variants.push(['dark', Array.isArray(darkMode) || 'class' == darkMode ? `${asArray(darkMode)[1] || '.dark'} &` : 'string' == typeof darkMode && 'media' != darkMode ? darkMode : // a custom selector '@media (prefers-color-scheme:dark)']); let h = 'function' == typeof hash$1 ? value => hash$1(value, hash) : hash$1 ? hash : identity; h !== identity && finalize.push(rule => ({ ...rule, n: rule.n && h(rule.n), d: rule.d?.replace(/--(tw(?:-[\w-]+)?)\b/g, (_, property) => '--' + h(property).replace('#', '')) })); let ctx = { theme: function ({ extend = {}, ...base }) { let resolved = {}, resolveContext = { get colors() { return theme('colors'); }, theme, // Stub implementation as negated values are automatically infered and do _not_ need to be in the theme negative() { return {}; }, breakpoints(screens) { let breakpoints = {}; for (let key in screens) 'string' == typeof screens[key] && (breakpoints['screen-' + key] = screens[key]); return breakpoints; } }; return theme; function theme(sectionKey, key, defaultValue, opacityValue) { if (sectionKey) { ({ 1: sectionKey, 2: opacityValue } = // eslint-disable-next-line no-sparse-arrays /^(\S+?)(?:\s*\/\s*([^/]+))?$/.exec(sectionKey) || [, sectionKey]); if (/[.[]/.test(sectionKey)) { let path = []; // dotted deep access: colors.gray.500 or spacing[2.5] sectionKey.replace(/\[([^\]]+)\]|([^.[]+)/g, (_, $1, $2 = $1) => path.push($2)); sectionKey = path.shift(); defaultValue = key; key = path.join('-'); } let section = resolved[sectionKey] || // two-step deref to allow extend section to reference base section Object.assign(Object.assign( // Make sure to not get into recursive calls resolved[sectionKey] = {}, deref(base, sectionKey)), deref(extend, sectionKey)); if (null == key) return section; key || (key = 'DEFAULT'); let value = section[key] ?? key.split('-').reduce((obj, prop) => obj?.[prop], section) ?? defaultValue; return opacityValue ? toColorValue(value, { opacityValue: resolveThemeFunction(opacityValue, theme) }) : value; } // Collect the whole theme let result = {}; for (let section1 of [...Object.keys(base), ...Object.keys(extend)]) result[section1] = theme(section1); return result; } function deref(source, section) { let value = source[section]; return ('function' == typeof value && (value = value(resolveContext)), value && /color|fill|stroke/i.test(section)) ? function flattenColorPalette(colors, path = []) { let flattend = {}; for (let key in colors) { let value = colors[key], keyPath = [...path, key]; flattend[keyPath.join('-')] = value; if ('DEFAULT' == key) { keyPath = path; flattend[path.join('-')] = value; } 'object' == typeof value && Object.assign(flattend, flattenColorPalette(value, keyPath)); } return flattend; }(value) : value; } }(theme), e: escape, h, s(property, value) { return stringify(property, value, ctx); }, d(section, key, color) { return darkColor(section, key, ctx, color); }, v(value) { return variantCache.has(value) || variantCache.set(value, find(value, variants, variantResolvers, getVariantResolver, ctx) || '&:' + value), variantCache.get(value); }, r(className, isDark) { let key = JSON.stringify([className, isDark]); return ruleCache.has(key) || ruleCache.set(key, !ignored(className, ctx) && find(className, rules, ruleResolvers, getRuleResolver, ctx, isDark)), ruleCache.get(key); }, f(rule) { return finalize.reduce((rule, p) => p(rule, ctx), rule); } }; return ctx; }(config), // Map of tokens to generated className cache = new Map(), // An array of precedence by index within the sheet // always sorted sortedPrecedences = [], // Cache for already inserted css rules // to prevent double insertions insertedRules = new Set(); sheet.resume(className => cache.set(className, className), (cssText, rule) => { sheet.insert(cssText, sortedPrecedences.length, rule); sortedPrecedences.push(rule); insertedRules.add(cssText); }); function insert(rule) { let finalRule = context.f(rule), cssText = stringify$1(finalRule); // If not already inserted if (cssText && !insertedRules.has(cssText)) { // Mark rule as inserted insertedRules.add(cssText); // Find the correct position let index = sortedInsertionIndex(sortedPrecedences, rule); // Insert sheet.insert(cssText, index, rule); // Update sorted index sortedPrecedences.splice(index, 0, rule); } return finalRule.n; } return Object.defineProperties(function tw(tokens) { if (!cache.size) for (let preflight of asArray(config.preflight)) { 'function' == typeof preflight && (preflight = preflight(context)); preflight && ('string' == typeof preflight ? translateWith('', Layer.b, parse(preflight), context, Layer.b, [], false, true) : serialize(preflight, {}, context, Layer.b)).forEach(insert); } tokens = '' + tokens; let className = cache.get(tokens); if (!className) { let classNames = new Set(); for (let rule of translate(parse(tokens), context)) classNames.add(rule.c).add(insert(rule)); className = [...classNames].filter(Boolean).join(' '); // Remember the generated class name cache.set(tokens, className).set(className, className); } return className; }, Object.getOwnPropertyDescriptors({ get target() { return sheet.target; }, theme: context.theme, config, snapshot() { let restoreSheet = sheet.snapshot(), insertedRules$ = new Set(insertedRules), cache$ = new Map(cache), sortedPrecedences$ = [...sortedPrecedences]; return () => { restoreSheet(); insertedRules = insertedRules$; cache = cache$; sortedPrecedences = sortedPrecedences$; }; }, clear() { sheet.clear(); insertedRules = new Set(); cache = new Map(); sortedPrecedences = []; }, destroy() { this.clear(); sheet.destroy(); } })); } /** * Simplified MutationRecord which allows us to pass an * ArrayLike (compatible with Array and NodeList) `addedNodes` and * omit other properties we are not interested in. */ function getStyleElement(selector) { let style = document.querySelector(selector || 'style[data-twind=""]'); if (!style || 'STYLE' != style.tagName) { style = document.createElement('style'); document.head.prepend(style); } return style.dataset.twind = 'claimed', style; } /** * @group Sheets * @param element * @returns */ function dom(element) { let target = element && 'string' != typeof element ? element : getStyleElement(element); return { target, snapshot() { // collect current rules let rules = Array.from(target.childNodes, node => node.textContent); return () => { // remove all existing rules this.clear(); // add all snapshot rules back // eslint-disable-next-line @typescript-eslint/unbound-method rules.forEach(this.insert); }; }, clear() { target.textContent = ''; }, destroy() { target.remove(); }, insert(cssText, index) { target.insertBefore(document.createTextNode(cssText), target.childNodes[index] || null); }, resume: noop }; } var i=new Map([["align-self","-ms-grid-row-align"],["color-adjust","-webkit-print-color-adjust"],["column-gap","grid-column-gap"],["forced-color-adjust","-ms-high-contrast-adjust"],["gap","grid-gap"],["grid-template-columns","-ms-grid-columns"],["grid-template-rows","-ms-grid-rows"],["justify-self","-ms-grid-column-align"],["margin-inline-end","-webkit-margin-end"],["margin-inline-start","-webkit-margin-start"],["mask-border","-webkit-mask-box-image"],["mask-border-outset","-webkit-mask-box-image-outset"],["mask-border-slice","-webkit-mask-box-image-slice"],["mask-border-source","-webkit-mask-box-image-source"],["mask-border-repeat","-webkit-mask-box-image-repeat"],["mask-border-width","-webkit-mask-box-image-width"],["overflow-wrap","word-wrap"],["padding-inline-end","-webkit-padding-end"],["padding-inline-start","-webkit-padding-start"],["print-color-adjust","color-adjust"],["row-gap","grid-row-gap"],["scroll-margin-bottom","scroll-snap-margin-bottom"],["scroll-margin-left","scroll-snap-margin-left"],["scroll-margin-right","scroll-snap-margin-right"],["scroll-margin-top","scroll-snap-margin-top"],["scroll-margin","scroll-snap-margin"],["text-combine-upright","-ms-text-combine-horizontal"]]);function r(r){return i.get(r)}function a(i){var r=/^(?:(text-(?:decoration$|e|or|si)|back(?:ground-cl|d|f)|box-d|mask(?:$|-[ispro]|-cl)|pr|hyphena|flex-d)|(tab-|column(?!-s)|text-align-l)|(ap)|u|hy)/i.exec(i);return r?r[1]?1:r[2]?2:r[3]?3:5:0}function t(i,r){var a=/^(?:(pos)|(cli)|(background-i)|(flex(?:$|-b)|(?:max-|min-)?(?:block-s|inl|he|widt))|dis)/i.exec(i);return a?a[1]?/^sti/i.test(r)?1:0:a[2]?/^pat/i.test(r)?1:0:a[3]?/^image-/i.test(r)?1:0:a[4]?"-"===r[3]?2:0:/^(?:inline-)?grid$/i.test(r)?4:0:0} let CSSPrefixFlags = [['-webkit-', 1], // 0b001 ['-moz-', 2], // 0b010 ['-ms-', 4]]; // 0b100 function presetAutoprefix() { return ({ stringify }) => ({ stringify(property, value, context) { let cssText = '', // Resolve aliases, e.g. `gap` -> `grid-gap` propertyAlias = r(property); propertyAlias && (cssText += stringify(propertyAlias, value, context) + ';'); // Prefix properties, e.g. `backdrop-filter` -> `-webkit-backdrop-filter` let propertyFlags = a(property), valueFlags = t(property, value); for (let prefix of CSSPrefixFlags) { propertyFlags & prefix[1] && (cssText += stringify(prefix[0] + property, value, context) + ';'); valueFlags & prefix[1] && (cssText += stringify(property, prefix[0] + value, context) + ';'); } /* Include the standardized declaration last */ /* https://css-tricks.com/ordering-css3-properties/ */ return cssText + stringify(property, value, context); } }); } /** * @module @twind/preset-tailwind/baseTheme */ /** * @experimental */let theme = { screens: { sm: '640px', md: '768px', lg: '1024px', xl: '1280px', '2xl': '1536px' }, columns: { auto: 'auto', // Handled by plugin, // 1: '1', // 2: '2', // 3: '3', // 4: '4', // 5: '5', // 6: '6', // 7: '7', // 8: '8', // 9: '9', // 10: '10', // 11: '11', // 12: '12', '3xs': '16rem', '2xs': '18rem', xs: '20rem', sm: '24rem', md: '28rem', lg: '32rem', xl: '36rem', '2xl': '42rem', '3xl': '48rem', '4xl': '56rem', '5xl': '64rem', '6xl': '72rem', '7xl': '80rem' }, spacing: { px: '1px', 0: '0px', ... /* #__PURE__ */linear(4, 'rem', 4, 0.5, 0.5), // 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', ... /* #__PURE__ */linear(12, 'rem', 4, 5), // 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', ... /* #__PURE__ */linear(64, 'rem', 4, 16, 4), // 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' }, durations: { 75: '75ms', 100: '100ms', 150: '150ms', 200: '200ms', 300: '300ms', 500: '500ms', 700: '700ms', 1000: '1000ms' }, animation: { none: 'none', spin: 'spin 1s linear infinite', ping: 'ping 1s cubic-bezier(0,0,0.2,1) infinite', pulse: 'pulse 2s cubic-bezier(0.4,0,0.6,1) infinite', bounce: 'bounce 1s infinite' }, aspectRatio: { auto: 'auto', square: '1/1', video: '16/9' }, backdropBlur: /* #__PURE__ */alias('blur'), backdropBrightness: /* #__PURE__ */alias('brightness'), backdropContrast: /* #__PURE__ */alias('contrast'), backdropGrayscale: /* #__PURE__ */alias('grayscale'), backdropHueRotate: /* #__PURE__ */alias('hueRotate'), backdropInvert: /* #__PURE__ */alias('invert'), backdropOpacity: /* #__PURE__ */alias('opacity'), backdropSaturate: /* #__PURE__ */alias('saturate'), backdropSepia: /* #__PURE__ */alias('sepia'), backgroundColor: /* #__PURE__ */alias('colors'), backgroundImage: { none: 'none' }, // These are built-in // 'gradient-to-t': 'linear-gradient(to top, var(--tw-gradient-stops))', // 'gradient-to-tr': 'linear-gradient(to top right, var(--tw-gradient-stops))', // 'gradient-to-r': 'linear-gradient(to right, var(--tw-gradient-stops))', // 'gradient-to-br': 'linear-gradient(to bottom right, var(--tw-gradient-stops))', // 'gradient-to-b': 'linear-gradient(to bottom, var(--tw-gradient-stops))', // 'gradient-to-bl': 'linear-gradient(to bottom left, var(--tw-gradient-stops))', // 'gradient-to-l': 'linear-gradient(to left, var(--tw-gradient-stops))', // 'gradient-to-tl': 'linear-gradient(to top left, var(--tw-gradient-stops))', backgroundOpacity: /* #__PURE__ */alias('opacity'), // backgroundPosition: { // // The following are already handled by the plugin: // // center, right, left, bottom, top // // 'bottom-10px-right-20px' -> bottom 10px right 20px // }, backgroundSize: { auto: 'auto', cover: 'cover', contain: 'contain' }, blur: { none: 'none', 0: '0', sm: '4px', DEFAULT: '8px', md: '12px', lg: '16px', xl: '24px', '2xl': '40px', '3xl': '64px' }, brightness: { ... /* #__PURE__ */linear(200, '', 100, 0, 50), // 0: '0', // 50: '.5', // 150: '1.5', // 200: '2', ... /* #__PURE__ */linear(110, '', 100, 90, 5), // 90: '.9', // 95: '.95', // 100: '1', // 105: '1.05', // 110: '1.1', 75: '0.75', 125: '1.25' }, borderColor: ({ theme }) => ({ DEFAULT: theme('colors.gray.200', 'currentColor'), ...theme('colors') }), borderOpacity: /* #__PURE__ */alias('opacity'), borderRadius: { none: '0px', sm: '0.125rem', DEFAULT: '0.25rem', md: '0.375rem', lg: '0.5rem', xl: '0.75rem', '2xl': '1rem', '3xl': '1.5rem', '1/2': '50%', full: '9999px' }, borderSpacing: /* #__PURE__ */alias('spacing'), borderWidth: { DEFAULT: '1px', ... /* #__PURE__ */exponential(8, 'px') }, // 0: '0px', // 2: '2px', // 4: '4px', // 8: '8px', boxShadow: { sm: '0 1px 2px 0 rgba(0,0,0,0.05)', DEFAULT: '0 1px 3px 0 rgba(0,0,0,0.1), 0 1px 2px -1px rgba(0,0,0,0.1)', md: '0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1)', lg: '0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1)', xl: '0 20px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.1)', '2xl': '0 25px 50px -12px rgba(0,0,0,0.25)', inner: 'inset 0 2px 4px 0 rgba(0,0,0,0.05)', none: '0 0 #0000' }, boxShadowColor: alias('colors'), // container: {}, // cursor: { // // Default values are handled by plugin // }, caretColor: /* #__PURE__ */alias('colors'), accentColor: ({ theme }) => ({ auto: 'auto', ...theme('colors') }), contrast: { ... /* #__PURE__ */linear(200, '', 100, 0, 50), // 0: '0', // 50: '.5', // 150: '1.5', // 200: '2', 75: '0.75', 125: '1.25' }, content: { none: 'none' }, divideColor: /* #__PURE__ */alias('borderColor'), divideOpacity: /* #__PURE__ */alias('borderOpacity'), divideWidth: /* #__PURE__ */alias('borderWidth'), dropShadow: { sm: '0 1px 1px rgba(0,0,0,0.05)', DEFAULT: ['0 1px 2px rgba(0,0,0,0.1)', '0 1px 1px rgba(0,0,0,0.06)'], md: ['0 4px 3px rgba(0,0,0,0.07)', '0 2px 2px rgba(0,0,0,0.06)'], lg: ['0 10px 8px rgba(0,0,0,0.04)', '0 4px 3px rgba(0,0,0,0.1)'], xl: ['0 20px 13px rgba(0,0,0,0.03)', '0 8px 5px rgba(0,0,0,0.08)'], '2xl': '0 25px 25px rgba(0,0,0,0.15)', none: '0 0 #0000' }, fill: ({ theme }) => ({ ...theme('colors'), none: 'none' }), grayscale: { DEFAULT: '100%', 0: '0' }, hueRotate: { 0: '0deg', 15: '15deg', 30: '30deg', 60: '60deg', 90: '90deg', 180: '180deg' }, invert: { DEFAULT: '100%', 0: '0' }, flex: { 1: '1 1 0%', auto: '1 1 auto', initial: '0 1 auto', none: 'none' }, flexBasis: ({ theme }) => ({ ...theme('spacing'), ...ratios(2, 6), // '1/2': '50%', // '1/3': '33.333333%', // '2/3': '66.666667%', // '1/4': '25%', // '2/4': '50%', // '3/4': '75%', // '1/5': '20%', // '2/5': '40%', // '3/5': '60%', // '4/5': '80%', // '1/6': '16.666667%', // '2/6': '33.333333%', // '3/6': '50%', // '4/6': '66.666667%', // '5/6': '83.333333%', ...ratios(12, 12), // '1/12': '8.333333%', // '2/12': '16.666667%', // '3/12': '25%', // '4/12': '33.333333%', // '5/12': '41.666667%', // '6/12': '50%', // '7/12': '58.333333%', // '8/12': '66.666667%', // '9/12': '75%', // '10/12': '83.333333%', // '11/12': '91.666667%', auto: 'auto', full: '100%' }), flexGrow: { DEFAULT: 1, 0: 0 }, flexShrink: { DEFAULT: 1, 0: 0 }, fontFamily: { sans: '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"'.split(','), serif: 'ui-serif,Georgia,Cambria,"Times New Roman",Times,serif'.split(','), mono: 'ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace'.split(',') }, fontSize: { xs: ['0.75rem', '1rem'], sm: ['0.875rem', '1.25rem'], base: ['1rem', '1.5rem'], lg: ['1.125rem', '1.75rem'], xl: ['1.25rem', '1.75rem'], '2xl': ['1.5rem', '2rem'], '3xl': ['1.875rem', '2.25rem'], '4xl': ['2.25rem', '2.5rem'], '5xl': ['3rem', '1'], '6xl': ['3.75rem', '1'], '7xl': ['4.5rem', '1'], '8xl': ['6rem', '1'], '9xl': ['8rem', '1'] }, fontWeight: { thin: '100', extralight: '200', light: '300', normal: '400', medium: '500', semibold: '600', bold: '700', extrabold: '800', black: '900' }, gap: /* #__PURE__ */alias('spacing'), gradientColorStops: /* #__PURE__ */alias('colors'), gridAutoColumns: { auto: 'auto', min: 'min-content', max: 'max-content', fr: 'minmax(0,1fr)' }, gridAutoRows: { auto: 'auto', min: 'min-content', max: 'max-content', fr: 'minmax(0,1fr)' }, gridColumn: { // span-X is handled by the plugin: span-1 -> span 1 / span 1 auto: 'auto', 'span-full': '1 / -1' }, // gridColumnEnd: { // // Defaults handled by plugin // }, // gridColumnStart: { // // Defaults handled by plugin // }, gridRow: { // span-X is handled by the plugin: span-1 -> span 1 / span 1 auto: 'auto', 'span-full': '1 / -1' }, // gridRowStart: { // // Defaults handled by plugin // }, // gridRowEnd: { // // Defaults handled by plugin // }, gridTemplateColumns: { // numbers are handled by the plugin: 1 -> repeat(1, minmax(0, 1fr)) none: 'none' }, gridTemplateRows: { // numbers are handled by the plugin: 1 -> repeat(1, minmax(0, 1fr)) none: 'none' }, height: ({ theme }) => ({ ...theme('spacing'), ...ratios(2, 6), // '1/2': '50%', // '1/3': '33.333333%', // '2/3': '66.666667%', // '1/4': '25%', // '2/4': '50%', // '3/4': '75%', // '1/5': '20%', // '2/5': '40%', // '3/5': '60%', // '4/5': '80%', // '1/6': '16.666667%', // '2/6': '33.333333%', // '3/6': '50%', // '4/6': '66.666667%', // '5/6': '83.333333%', min: 'min-content', max: 'max-content', fit: 'fit-content', auto: 'auto', full: '100%', screen: '100vh' }), inset: ({ theme }) => ({ ...theme('spacing'), ...ratios(2, 4), // '1/2': '50%', // '1/3': '33.333333%', // '2/3': '66.666667%', // '1/4': '25%', // '2/4': '50%', // '3/4': '75%', auto: 'auto', full: '100%' }), keyframes: { spin: { from: { transform: 'rotate(0deg)' }, to: { transform: 'rotate(360deg)' } }, ping: { '0%': { transform: 'scale(1)', opacity: '1' }, '75%,100%': { transform: 'scale(2)', opacity: '0' } }, pulse: { '0%,100%': { opacity: '1' }, '50%': { opacity: '.5' } }, bounce: { '0%, 100%': { transform: 'translateY(-25%)', animationTimingFunction: 'cubic-bezier(0.8,0,1,1)' }, '50%': { transform: 'none', animationTimingFunction: 'cubic-bezier(0,0,0.2,1)' } } }, letterSpacing: { tighter: '-0.05em', tight: '-0.025em', normal: '0em', wide: '0.025em', wider: '0.05em', widest: '0.1em' }, lineHeight: { ... /* #__PURE__ */linear(10, 'rem', 4, 3), // 3: '.75rem', // 4: '1rem', // 5: '1.25rem', // 6: '1.5rem', // 7: '1.75rem', // 8: '2rem', // 9: '2.25rem', // 10: '2.5rem', none: '1', tight: '1.25', snug: '1.375', normal: '1.5', relaxed: '1.625', loose: '2' }, // listStyleType: { // // Defaults handled by plugin // }, margin: ({ theme }) => ({ auto: 'auto', ...theme('spacing') }), maxHeight: ({ theme }) => ({ full: '100%', min: 'min-content', max: 'max-content', fit: 'fit-content', screen: '100vh', ...theme('spacing') }), maxWidth: ({ theme, breakpoints }) => ({ ...breakpoints(theme('screens')), none: 'none', 0: '0rem', xs: '20rem', sm: '24rem', md: '28rem', lg: '32rem', xl: '36rem', '2xl': '42rem', '3xl': '48rem', '4xl': '56rem', '5xl': '64rem', '6xl': '72rem', '7xl': '80rem', full: '100%', min: 'min-content', max: 'max-content', fit: 'fit-content', prose: '65ch' }), minHeight: { 0: '0px', full: '100%', min: 'min-content', max: 'max-content', fit: 'fit-content', screen: '100vh' }, minWidth: { 0: '0px', full: '100%', min: 'min-content', max: 'max-content', fit: 'fit-content' }, // objectPosition: { // // The plugins joins all arguments by default // }, opacity: { ... /* #__PURE__ */linear(100, '', 100, 0, 10), // 0: '0', // 10: '0.1', // 20: '0.2', // 30: '0.3', // 40: '0.4', // 60: '0.6', // 70: '0.7', // 80: '0.8', // 90: '0.9', // 100: '1', 5: '0.05', 25: '0.25', 75: '0.75', 95: '0.95' }, order: { // Handled by plugin // 1: '1', // 2: '2', // 3: '3', // 4: '4', // 5: '5', // 6: '6', // 7: '7', // 8: '8', // 9: '9', // 10: '10', // 11: '11', // 12: '12', first: '-9999', last: '9999', none: '0' }, padding: /* #__PURE__ */alias('spacing'), placeholderColor: /* #__PURE__ */alias('colors'), placeholderOpacity: /* #__PURE__ */alias('opacity'), outlineColor: /* #__PURE__ */alias('colors'), outlineOffset: /* #__PURE__ */exponential(8, 'px'), // 0: '0px', // 1: '1px', // 2: '2px', // 4: '4px', // 8: '8px',, outlineWidth: /* #__PURE__ */exponential(8, 'px'), // 0: '0px', // 1: '1px', // 2: '2px', // 4: '4px', // 8: '8px',, ringColor: ({ theme }) => ({ ...theme('colors'), DEFAULT: '#3b82f6' }), ringOffsetColor: /* #__PURE__ */alias('colors'), ringOffsetWidth: /* #__PURE__ */exponential(8, 'px'), // 0: '0px', // 1: '1px', // 2: '2px', // 4: '4px', // 8: '8px',, ringOpacity: ({ theme }) => ({ ...theme('opacity'), DEFAULT: '0.5' }), ringWidth: { DEFAULT: '3px', ... /* #__PURE__ */exponential(8, 'px') }, // 0: '0px', // 1: '1px', // 2: '2px', // 4: '4px', // 8: '8px', rotate: { ... /* #__PURE__ */exponential(2, 'deg'), // 0: '0deg', // 1: '1deg', // 2: '2deg', ... /* #__PURE__ */exponential(12, 'deg', 3), // 3: '3deg', // 6: '6deg', // 12: '12deg', ... /* #__PURE__ */exponential(180, 'deg', 45) }, // 45: '45deg', // 90: '90deg', // 180: '180deg', saturate: /* #__PURE__ */linear(200, '', 100, 0, 50), // 0: '0', // 50: '.5', // 100: '1', // 150: '1.5', // 200: '2', scale: { ... /* #__PURE__ */linear(150, '', 100, 0, 50), // 0: '0', // 50: '.5', // 150: '1.5', ... /* #__PURE__ */linear(110, '', 100, 90, 5), // 90: '.9', // 95: '.95', // 100: '1', // 105: '1.05', // 110: '1.1', 75: '0.75', 125: '1.25' }, scrollMargin: /* #__PURE__ */alias('spacing'), scrollPadding: /* #__PURE__ */alias('spacing'), sepia: { 0: '0', DEFAULT: '100%' }, skew: { ... /* #__PURE__ */exponential(2, 'deg'), // 0: '0deg', // 1: '1deg', // 2: '2deg', ... /* #__PURE__ */exponential(12, 'deg', 3) }, // 3: '3deg', // 6: '6deg', // 12: '12deg', space: /* #__PURE__ */alias('spacing'), stroke: ({ theme }) => ({ ...theme('colors'), none: 'none' }), strokeWidth: /* #__PURE__ */linear(2), // 0: '0', // 1: '1', // 2: '2',, textColor: /* #__PURE__ */alias('colors'), textDecorationColor: /* #__PURE__ */alias('colors'), textDecorationThickness: { 'from-font': 'from-font', auto: 'auto', ... /* #__PURE__ */exponential(8, 'px') }, // 0: '0px', // 1: '1px', // 2: '2px', // 4: '4px', // 8: '8px', textUnderlineOffset: { auto: 'auto', ... /* #__PURE__ */exponential(8, 'px') }, // 0: '0px', // 1: '1px', // 2: '2px', // 4: '4px', // 8: '8px', textIndent: /* #__PURE__ */alias('spacing'), textOpacity: /* #__PURE__ */alias('opacity'), // transformOrigin: { // // The following are already handled by the plugin: // // center, right, left, bottom, top // // 'bottom-10px-right-20px' -> bottom 10px right 20px // }, transitionDuration: ({ theme }) => ({ ...theme('durations'), DEFAULT: '150ms' }), transitionDelay: /* #__PURE__ */alias('durations'), transitionProperty: { none: 'none', all: 'all', DEFAULT: 'color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter', colors: 'color,background-color,border-color,text-decoration-color,fill,stroke', opacity: 'opacity', shadow: 'box-shadow', transform: 'transform' }, transitionTimingFunction: { DEFAULT: 'cubic-bezier(0.4,0,0.2,1)', linear: 'linear', in: 'cubic-bezier(0.4,0,1,1)', out: 'cubic-bezier(0,0,0.2,1)', 'in-out': 'cubic-bezier(0.4,0,0.2,1)' }, translate: ({ theme }) => ({ ...theme('spacing'), ...ratios(2, 4), // '1/2': '50%', // '1/3': '33.333333%', // '2/3': '66.666667%', // '1/4': '25%', // '2/4': '50%', // '3/4': '75%', full: '100%' }), width: ({ theme }) => ({ min: 'min-content', max: 'max-content', fit: 'fit-content', screen: '100vw', ...theme('flexBasis') }), willChange: { scroll: 'scroll-position' }, // other options handled by rules // auto: 'auto', // contents: 'contents', // transform: 'transform', zIndex: { ... /* #__PURE__ */linear(50, '', 1, 0, 10), // 0: '0', // 10: '10', // 20: '20', // 30: '30', // 40: '40', // 50: '50', auto: 'auto' } }; // '1/2': '50%', // '1/3': '33.333333%', // '2/3': '66.666667%', // '1/4': '25%', // '2/4': '50%', // '3/4': '75%', // '1/5': '20%', // '2/5': '40%', // '3/5': '60%', // '4/5': '80%', // '1/6': '16.666667%', // '2/6': '33.333333%', // '3/6': '50%', // '4/6': '66.666667%', // '5/6': '83.333333%', function ratios(start, end) { let result = {}; do // XXX: using var to avoid strange bug when generating cjs where `= 1` is removed // eslint-disable-next-line no-var for (var dividend = 1; dividend < start; dividend++) result[`${dividend}/${start}`] = Number((dividend / start * 100).toFixed(6)) + '%'; while (++start <= end); return result; } // 0: '0px', // 2: '2px', // 4: '4px', // 8: '8px', function exponential(stop, unit, start = 0) { let result = {}; for (; start <= stop; start = 2 * start || 1) result[start] = start + unit; return result; } // 3: '.75rem', // 4: '1rem', // 5: '1.25rem', // 6: '1.5rem', // 7: '1.75rem', // 8: '2rem', // 9: '2.25rem', // 10: '2.5rem', function linear(stop, unit = '', divideBy = 1, start = 0, step = 1, result = {}) // eslint-disable-next-line max-params { for (; start <= stop; start += step) result[start] = start / divideBy + unit; return result; } function alias(section) { return ({ theme }) => theme(section); } let preflight = { /* 1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) 2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) */ '*,::before,::after': { boxSizing: 'border-box', /* 1 */borderWidth: '0', /* 2 */borderStyle: 'solid', /* 2 */borderColor: 'theme(borderColor.DEFAULT, currentColor)' }, /* 2 */'::before,::after': { '--tw-content': "''" }, /* 1. Use a consistent sensible line-height in all browsers. 2. Prevent adjustments of font size after orientation changes in iOS. 3. Use a more readable tab size. 4. Use the user's configured `sans` font-family by default. 5. Use the user's configured `sans` font-feature-settings by default. */ html: { lineHeight: 1.5, /* 1 */WebkitTextSizeAdjust: '100%', /* 2 */MozTabSize: '4', /* 3 */tabSize: 4, /* 3 */fontFamily: `theme(fontFamily.sans, ${theme.fontFamily.sans})`, /* 4 */fontFeatureSettings: 'theme(fontFamily.sans[1].fontFeatureSettings, normal)' }, /* 5 */ /* 1. Remove the margin in all browsers. 2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. */body: { margin: '0', /* 1 */lineHeight: 'inherit' }, /* 2 */ /* 1. Add the correct height in Firefox. 2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) 3. Ensure horizontal rules are visible by default. */hr: { height: '0', /* 1 */color: 'inherit', /* 2 */borderTopWidth: '1px' }, /* 3 */ /* Add the correct text decoration in Chrome, Edge, and Safari. */'abbr:where([title])': { textDecoration: 'underline dotted' }, /* Remove the default font size and weight for headings. */ 'h1,h2,h3,h4,h5,h6': { fontSize: 'inherit', fontWeight: 'inherit' }, /* Reset links to optimize for opt-in styling instead of opt-out. */ a: { color: 'inherit', textDecoration: 'inherit' }, /* Add the correct font weight in Edge and Safari. */ 'b,strong': { fontWeight: 'bolder' }, /* 1. Use the user's configured `mono` font family by default. 2. Use the user's configured `mono` font-feature-settings by default. 3. Correct the odd `em` font sizing in all browsers. */ 'code,kbd,samp,pre': { fontFamily: `theme(fontFamily.mono, ${theme.fontFamily.mono})`, fontFeatureSettings: 'theme(fontFamily.mono[1].fontFeatureSettings, normal)', fontSize: '1em' }, /* Add the correct font size in all browsers. */ small: { fontSize: '80%' }, /* Prevent `sub` and `sup` elements from affecting the line height in all browsers. */ 'sub,sup': { fontSize: '75%', lineHeight: 0, position: 'relative', verticalAlign: 'baseline' }, sub: { bottom: '-0.25em' }, sup: { top: '-0.5em' }, /* 1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) 2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) 3. Remove gaps between table borders by default. */ table: { textIndent: '0', /* 1 */borderColor: 'inherit', /* 2 */borderCollapse: 'collapse' }, /* 3 */ /* 1. Change the font styles in all browsers. 2. Remove the margin in Firefox and Safari. 3. Remove default padding in all browsers. */'button,input,optgroup,select,textarea': { fontFamily: 'inherit', /* 1 */fontSize: '100%', /* 1 */lineHeight: 'inherit', /* 1 */color: 'inherit', /* 1 */margin: '0', /* 2 */padding: '0' }, /* 3 */ /* Remove the inheritance of text transform in Edge and Firefox. */'button,select': { textTransform: 'none' }, /* 1. Correct the inability to style clickable types in iOS and Safari. 2. Remove default button styles. */ "button,[type='button'],[type='reset'],[type='submit']": { WebkitAppearance: 'button', /* 1 */backgroundColor: 'transparent', /* 2 */backgroundImage: 'none' }, /* 4 */ /* Use the modern Firefox focus style for all focusable elements. */':-moz-focusring': { outline: 'auto' }, /* Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) */ ':-moz-ui-invalid': { boxShadow: 'none' }, /* Add the correct vertical alignment in Chrome and Firefox. */ progress: { verticalAlign: 'baseline' }, /* Correct the cursor style of increment and decrement buttons in Safari. */ '::-webkit-inner-spin-button,::-webkit-outer-spin-button': { height: 'auto' }, /* 1. Correct the odd appearance in Chrome and Safari. 2. Correct the outline style in Safari. */ "[type='search']": { WebkitAppearance: 'textfield', /* 1 */outlineOffset: '-2px' }, /* 2 */ /* Remove the inner padding in Chrome and Safari on macOS. */'::-webkit-search-decoration': { WebkitAppearance: 'none' }, /* 1. Correct the inability to style clickable types in iOS and Safari. 2. Change font properties to `inherit` in Safari. */ '::-webkit-file-upload-button': { WebkitAppearance: 'button', /* 1 */font: 'inherit' }, /* 2 */ /* Add the correct display in Chrome and Safari. */summary: { display: 'list-item' }, /* Removes the default spacing and border for appropriate elements. */ 'blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre': { margin: '0' }, fieldset: { margin: '0', padding: '0' }, legend: { padding: '0' }, 'ol,ul,menu': { listStyle: 'none', margin: '0', padding: '0' }, /* Prevent resizing textareas horizontally by default. */ textarea: { resize: 'vertical' }, /* 1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) 2. Set the default placeholder color to the user's configured gray 400 color. */ 'input::placeholder,textarea::placeholder': { opacity: 1, /* 1 */color: 'theme(colors.gray.400, #9ca3af)' }, /* 2 */ /* Set the default cursor for buttons. */'button,[role="button"]': { cursor: 'pointer' }, /* Make sure disabled buttons don't get the pointer cursor. */ ':disabled': { cursor: 'default' }, /* 1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) 2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) This can trigger a poorly considered lint error in some tools but is included by design. */ 'img,svg,video,canvas,audio,iframe,embed,object': { display: 'block', /* 1 */verticalAlign: 'middle' }, /* 2 */ /* Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) */'img,video': { maxWidth: '100%', height: 'auto' }, /* Make elements with the HTML hidden attribute stay hidden by default */'[hidden]': { display: 'none' } }; // indirection wrapper to remove autocomplete functions from production bundles let rules = [/* arbitrary properties: [paint-order:markers] */match('\\[([-\\w]+):(.+)]', ({ 1: $1, 2: $2 }, context) => ({ '@layer overrides': { '&': { [$1]: arbitrary(`[${$2}]`, '', context) } } })), /* Styling based on parent and peer state */match('(group|peer)([~/][^-[]+)?', ({ input }, { h }) => [{ c: h(input) }]), /* LAYOUT */matchTheme('aspect-', 'aspectRatio'), match('container', (_, { theme }) => { let { screens = theme('screens'), center, padding } = theme('container'), rules = { width: '100%', marginRight: center && 'auto', marginLeft: center && 'auto', ...paddingFor('xs') }; for (let screen in screens) { let value = screens[screen]; 'string' == typeof value && (rules[mql(value)] = { '&': { maxWidth: value, ...paddingFor(screen) } }); } return rules; function paddingFor(screen) { let value = padding && ('string' == typeof padding ? padding : padding[screen] || padding.DEFAULT); if (value) return { paddingRight: value, paddingLeft: value }; } }), // Content matchTheme('content-', 'content', ({ _ }) => ({ '--tw-content': _, content: 'var(--tw-content)' })), // Box Decoration Break match('(?:box-)?decoration-(slice|clone)', 'boxDecorationBreak'), // Box Sizing match('box-(border|content)', 'boxSizing', ({ 1: $1 }) => $1 + '-box'), // Display match('hidden', { display: 'none' }), // Table Layout match('table-(auto|fixed)', 'tableLayout'), match(['(block|flex|table|grid|inline|contents|flow-root|list-item)', '(inline-(block|flex|table|grid))', '(table-(caption|cell|column|row|(column|row|footer|header)-group))'], 'display'), // Floats '(float)-(left|right|none)', // Clear '(clear)-(left|right|none|both)', // Overflow '(overflow(?:-[xy])?)-(auto|hidden|clip|visible|scroll)', // Isolation '(isolation)-(auto)', // Isolation match('isolate', 'isolation'), // Object Fit match('object-(contain|cover|fill|none|scale-down)', 'objectFit'), // Object Position matchTheme('object-', 'objectPosition'), match('object-(top|bottom|center|(left|right)(-(top|bottom))?)', 'objectPosition', spacify), // Overscroll Behavior match('overscroll(-[xy])?-(auto|contain|none)', ({ 1: $1 = '', 2: $2 }) => ({ ['overscroll-behavior' + $1]: $2 })), // Position match('(static|fixed|absolute|relative|sticky)', 'position'), // Top / Right / Bottom / Left matchTheme('-?inset(-[xy])?(?:$|-)', 'inset', ({ 1: $1, _ }) => ({ top: '-x' != $1 && _, right: '-y' != $1 && _, bottom: '-x' != $1 && _, left: '-y' != $1 && _ })), matchTheme('-?(top|bottom|left|right)(?:$|-)', 'inset'), // Visibility match('(visible|collapse)', 'visibility'), match('invisible', { visibility: 'hidden' }), // Z-Index matchTheme('-?z-', 'zIndex'), /* FLEXBOX */ // Flex Direction match('flex-((row|col)(-reverse)?)', 'flexDirection', columnify), match('flex-(wrap|wrap-reverse|nowrap)', 'flexWrap'), matchTheme('(flex-(?:grow|shrink))(?:$|-)'), /*, 'flex-grow' | flex-shrink */matchTheme('(flex)-'), /*, 'flex' */matchTheme('grow(?:$|-)', 'flexGrow'), matchTheme('shrink(?:$|-)', 'flexShrink'), matchTheme('basis-', 'flexBasis'), matchTheme('-?(order)-'), /*, 'order' */'-?(order)-(\\d+)', /* GRID */ // Grid Template Columns matchTheme('grid-cols-', 'gridTemplateColumns'), match('grid-cols-(\\d+)', 'gridTemplateColumns', gridTemplate), // Grid Column Start / End matchTheme('col-', 'gridColumn'), match('col-(span)-(\\d+)', 'gridColumn', span), matchTheme('col-start-', 'gridColumnStart'), match('col-start-(auto|\\d+)', 'gridColumnStart'), matchTheme('col-end-', 'gridColumnEnd'), match('col-end-(auto|\\d+)', 'gridColumnEnd'), // Grid Template Rows matchTheme('grid-rows-', 'gridTemplateRows'), match('grid-rows-(\\d+)', 'gridTemplateRows', gridTemplate), // Grid Row Start / End matchTheme('row-', 'gridRow'), match('row-(span)-(\\d+)', 'gridRow', span), matchTheme('row-start-', 'gridRowStart'), match('row-start-(auto|\\d+)', 'gridRowStart'), matchTheme('row-end-', 'gridRowEnd'), match('row-end-(auto|\\d+)', 'gridRowEnd'), // Grid Auto Flow match('grid-flow-((row|col)(-dense)?)', 'gridAutoFlow', match => spacify(columnify(match))), match('grid-flow-(dense)', 'gridAutoFlow'), // Grid Auto Columns matchTheme('auto-cols-', 'gridAutoColumns'), // Grid Auto Rows matchTheme('auto-rows-', 'gridAutoRows'), // Gap matchTheme('gap-x(?:$|-)', 'gap', 'columnGap'), matchTheme('gap-y(?:$|-)', 'gap', 'rowGap'), matchTheme('gap(?:$|-)', 'gap'), /* BOX ALIGNMENT */ // Justify Items // Justify Self '(justify-(?:items|self))-', // Justify Content match('justify-', 'justifyContent', convertContentValue), // Align Content // Align Items // Align Self match('(content|items|self)-', match => ({ ['align-' + match[1]]: convertContentValue(match) })), // Place Content // Place Items // Place Self match('(place-(content|items|self))-', ({ 1: $1, $$ }) => ({ [$1]: ('wun'.includes($$[3]) ? 'space-' : '') + $$ })), /* SPACING */ // Padding matchTheme('p([xytrbl])?(?:$|-)', 'padding', edge('padding')), // Margin matchTheme('-?m([xytrbl])?(?:$|-)', 'margin', edge('margin')), // Space Between matchTheme('-?space-(x|y)(?:$|-)', 'space', ({ 1: $1, _ }) => ({ '&>:not([hidden])~:not([hidden])': { [`--tw-space-${$1}-reverse`]: '0', ['margin-' + { y: 'top', x: 'left' }[$1]]: `calc(${_} * calc(1 - var(--tw-space-${$1}-reverse)))`, ['margin-' + { y: 'bottom', x: 'right' }[$1]]: `calc(${_} * var(--tw-space-${$1}-reverse))` } })), match('space-(x|y)-reverse', ({ 1: $1 }) => ({ '&>:not([hidden])~:not([hidden])': { [`--tw-space-${$1}-reverse`]: '1' } })), /* SIZING */ // Width matchTheme('w-', 'width'), // Min-Width matchTheme('min-w-', 'minWidth'), // Max-Width matchTheme('max-w-', 'maxWidth'), // Height matchTheme('h-', 'height'), // Min-Height matchTheme('min-h-', 'minHeight'), // Max-Height matchTheme('max-h-', 'maxHeight'), /* TYPOGRAPHY */ // Font Weight matchTheme('font-', 'fontWeight'), // Font Family matchTheme('font-', 'fontFamily', ({ _ }) => { return 'string' == typeof (_ = asArray(_))[1] ? { fontFamily: join(_) } : { fontFamily: join(_[0]), ..._[1] }; }), // Font Smoothing match('antialiased', { WebkitFontSmoothing: 'antialiased', MozOsxFontSmoothing: 'grayscale' }), match('subpixel-antialiased', { WebkitFontSmoothing: 'auto', MozOsxFontSmoothing: 'auto' }), // Font Style match('italic', 'fontStyle'), match('not-italic', { fontStyle: 'normal' }), // Font Variant Numeric match('(ordinal|slashed-zero|(normal|lining|oldstyle|proportional|tabular)-nums|(diagonal|stacked)-fractions)', ({ 1: $1, 2: $2 = '', 3: $3 }) => // normal-nums 'normal' == $2 ? { fontVariantNumeric: 'normal' } : { ['--tw-' + ($3 ? // diagonal-fractions, stacked-fractions 'numeric-fraction' : 'pt'.includes($2[0]) ? // proportional-nums, tabular-nums 'numeric-spacing' : $2 ? // lining-nums, oldstyle-nums 'numeric-figure' : // ordinal, slashed-zero $1)]: $1, fontVariantNumeric: 'var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)', ...asDefaults({ '--tw-ordinal': 'var(--tw-empty,/*!*/ /*!*/)', '--tw-slashed-zero': 'var(--tw-empty,/*!*/ /*!*/)', '--tw-numeric-figure': 'var(--tw-empty,/*!*/ /*!*/)', '--tw-numeric-spacing': 'var(--tw-empty,/*!*/ /*!*/)', '--tw-numeric-fraction': 'var(--tw-empty,/*!*/ /*!*/)' }) }), // Letter Spacing matchTheme('tracking-', 'letterSpacing'), // Line Height matchTheme('leading-', 'lineHeight'), // List Style Position match('list-(inside|outside)', 'listStylePosition'), // List Style Type matchTheme('list-', 'listStyleType'), match('list-', 'listStyleType'), // Placeholder Opacity matchTheme('placeholder-opacity-', 'placeholderOpacity', ({ _ }) => ({ '&::placeholder': { '--tw-placeholder-opacity': _ } })), // Placeholder Color matchColor('placeholder-', { property: 'color', selector: '&::placeholder' }), // Text Alignment match('text-(left|center|right|justify|start|end)', 'textAlign'), match('text-(ellipsis|clip)', 'textOverflow'), // Text Opacity matchTheme('text-opacity-', 'textOpacity', '--tw-text-opacity'), // Text Color matchColor('text-', { property: 'color' }), // Font Size matchTheme('text-', 'fontSize', ({ _ }) => 'string' == typeof _ ? { fontSize: _ } : { fontSize: _[0], ...('string' == typeof _[1] ? { lineHeight: _[1] } : _[1]) }), // Text Indent matchTheme('indent-', 'textIndent'), // Text Decoration match('(overline|underline|line-through)', 'textDecorationLine'), match('no-underline', { textDecorationLine: 'none' }), // Text Underline offset matchTheme('underline-offset-', 'textUnderlineOffset'), // Text Decoration Color matchColor('decoration-', { section: 'textDecorationColor', opacityVariable: false, opacitySection: 'opacity' }), // Text Decoration Thickness matchTheme('decoration-', 'textDecorationThickness'), // Text Decoration Style match('decoration-', 'textDecorationStyle'), // Text Transform match('(uppercase|lowercase|capitalize)', 'textTransform'), match('normal-case', { textTransform: 'none' }), // Text Overflow match('truncate', { overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }), // Vertical Alignment match('align-', 'verticalAlign'), // Whitespace match('whitespace-', 'whiteSpace'), // Word Break match('break-normal', { wordBreak: 'normal', overflowWrap: 'normal' }), match('break-words', { overflowWrap: 'break-word' }), match('break-all', { wordBreak: 'break-all' }), match('break-keep', { wordBreak: 'keep-all' }), // Caret Color matchColor('caret-', { // section: 'caretColor', opacityVariable: false, opacitySection: 'opacity' }), // Accent Color matchColor('accent-', { // section: 'accentColor', opacityVariable: false, opacitySection: 'opacity' }), // Gradient Color Stops match('bg-gradient-to-([trbl]|[tb][rl])', 'backgroundImage', ({ 1: $1 }) => `linear-gradient(to ${position($1, ' ')},var(--tw-gradient-stops))`), matchColor('from-', { section: 'gradientColorStops', opacityVariable: false, opacitySection: 'opacity' }, ({ _ }) => ({ '--tw-gradient-from': _.value, '--tw-gradient-to': _.color({ opacityValue: '0' }), '--tw-gradient-stops': "var(--tw-gradient-from),var(--tw-gradient-to)" })), matchColor('via-', { section: 'gradientColorStops', opacityVariable: false, opacitySection: 'opacity' }, ({ _ }) => ({ '--tw-gradient-to': _.color({ opacityValue: '0' }), '--tw-gradient-stops': `var(--tw-gradient-from),${_.value},var(--tw-gradient-to)` })), matchColor('to-', { section: 'gradientColorStops', property: '--tw-gradient-to', opacityVariable: false, opacitySection: 'opacity' }), /* BACKGROUNDS */ // Background Attachment match('bg-(fixed|local|scroll)', 'backgroundAttachment'), // Background Origin match('bg-origin-(border|padding|content)', 'backgroundOrigin', ({ 1: $1 }) => $1 + '-box'), // Background Repeat match(['bg-(no-repeat|repeat(-[xy])?)', 'bg-repeat-(round|space)'], 'backgroundRepeat'), // Background Blend Mode match('bg-blend-', 'backgroundBlendMode'), // Background Clip match('bg-clip-(border|padding|content|text)', 'backgroundClip', ({ 1: $1 }) => $1 + ('text' == $1 ? '' : '-box')), // Background Opacity matchTheme('bg-opacity-', 'backgroundOpacity', '--tw-bg-opacity'), // Background Color // bg-${backgroundColor}/${backgroundOpacity} matchColor('bg-', { section: 'backgroundColor' }), // Background Image // supported arbitrary types are: length, color, angle, list matchTheme('bg-', 'backgroundImage'), // Background Position matchTheme('bg-', 'backgroundPosition'), match('bg-(top|bottom|center|(left|right)(-(top|bottom))?)', 'backgroundPosition', spacify), // Background Size matchTheme('bg-', 'backgroundSize'), /* BORDERS */ // Border Radius matchTheme('rounded(?:$|-)', 'borderRadius'), matchTheme('rounded-([trbl]|[tb][rl])(?:$|-)', 'borderRadius', ({ 1: $1, _ }) => { let corners = { t: ['tl', 'tr'], r: ['tr', 'br'], b: ['bl', 'br'], l: ['bl', 'tl'] }[$1] || [$1, $1]; return { [`border-${position(corners[0])}-radius`]: _, [`border-${position(corners[1])}-radius`]: _ }; }), // Border Collapse match('border-(collapse|separate)', 'borderCollapse'), // Border Opacity matchTheme('border-opacity(?:$|-)', 'borderOpacity', '--tw-border-opacity'), // Border Style match('border-(solid|dashed|dotted|double|none)', 'borderStyle'), // Border Spacing matchTheme('border-spacing(-[xy])?(?:$|-)', 'borderSpacing', ({ 1: $1, _ }) => ({ ...asDefaults({ '--tw-border-spacing-x': '0', '--tw-border-spacing-y': '0' }), ['--tw-border-spacing' + ($1 || '-x')]: _, ['--tw-border-spacing' + ($1 || '-y')]: _, 'border-spacing': 'var(--tw-border-spacing-x) var(--tw-border-spacing-y)' })), // Border Color matchColor('border-([xytrbl])-', { section: 'borderColor' }, edge('border', 'Color')), matchColor('border-'), // Border Width matchTheme('border-([xytrbl])(?:$|-)', 'borderWidth', edge('border', 'Width')), matchTheme('border(?:$|-)', 'borderWidth'), // Divide Opacity matchTheme('divide-opacity(?:$|-)', 'divideOpacity', ({ _ }) => ({ '&>:not([hidden])~:not([hidden])': { '--tw-divide-opacity': _ } })), // Divide Style match('divide-(solid|dashed|dotted|double|none)', ({ 1: $1 }) => ({ '&>:not([hidden])~:not([hidden])': { borderStyle: $1 } })), // Divide Width match('divide-([xy]-reverse)', ({ 1: $1 }) => ({ '&>:not([hidden])~:not([hidden])': { ['--tw-divide-' + $1]: '1' } })), matchTheme('divide-([xy])(?:$|-)', 'divideWidth', ({ 1: $1, _ }) => { let edges = { x: 'lr', y: 'tb' }[$1]; return { '&>:not([hidden])~:not([hidden])': { [`--tw-divide-${$1}-reverse`]: '0', [`border-${position(edges[0])}Width`]: `calc(${_} * calc(1 - var(--tw-divide-${$1}-reverse)))`, [`border-${position(edges[1])}Width`]: `calc(${_} * var(--tw-divide-${$1}-reverse))` } }; }), // Divide Color matchColor('divide-', { // section: $0.replace('-', 'Color') -> 'divideColor' property: 'borderColor', // opacityVariable: '--tw-border-opacity', // opacitySection: section.replace('Color', 'Opacity') -> 'divideOpacity' selector: '&>:not([hidden])~:not([hidden])' }), // Ring Offset Opacity matchTheme('ring-opacity(?:$|-)', 'ringOpacity', '--tw-ring-opacity'), // Ring Offset Color matchColor('ring-offset-', { // section: 'ringOffsetColor', property: '--tw-ring-offset-color', opacityVariable: false }), // opacitySection: section.replace('Color', 'Opacity') -> 'ringOffsetOpacity' // Ring Offset Width matchTheme('ring-offset(?:$|-)', 'ringOffsetWidth', '--tw-ring-offset-width'), // Ring Inset match('ring-inset', { '--tw-ring-inset': 'inset' }), // Ring Color matchColor('ring-', { // section: 'ringColor', property: '--tw-ring-color' }), // opacityVariable: '--tw-ring-opacity', // opacitySection: section.replace('Color', 'Opacity') -> 'ringOpacity' // Ring Width matchTheme('ring(?:$|-)', 'ringWidth', ({ _ }, { theme }) => ({ ...asDefaults({ '--tw-ring-offset-shadow': '0 0 #0000', '--tw-ring-shadow': '0 0 #0000', '--tw-shadow': '0 0 #0000', '--tw-shadow-colored': '0 0 #0000', // Within own declaration to have the defaults above to be merged with defaults from shadow '&': { '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)', '--tw-ring-offset-width': theme('ringOffsetWidth', '', '0px'), '--tw-ring-offset-color': toColorValue(theme('ringOffsetColor', '', '#fff')), '--tw-ring-color': toColorValue(theme('ringColor', '', '#93c5fd'), { opacityVariable: '--tw-ring-opacity' }), '--tw-ring-opacity': theme('ringOpacity', '', '0.5') } }), '--tw-ring-offset-shadow': "var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)", '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(${_} + var(--tw-ring-offset-width)) var(--tw-ring-color)`, boxShadow: "var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)" })), /* EFFECTS */ // Box Shadow Color matchColor('shadow-', { section: 'boxShadowColor', opacityVariable: false, opacitySection: 'opacity' }, ({ _ }) => ({ '--tw-shadow-color': _.value, '--tw-shadow': 'var(--tw-shadow-colored)' })), // Box Shadow matchTheme('shadow(?:$|-)', 'boxShadow', ({ _ }) => ({ ...asDefaults({ '--tw-ring-offset-shadow': '0 0 #0000', '--tw-ring-shadow': '0 0 #0000', '--tw-shadow': '0 0 #0000', '--tw-shadow-colored': '0 0 #0000' }), '--tw-shadow': join(_), // replace all colors with reference to --tw-shadow-colored // this matches colors after non-comma char (keyword, offset) before comma or the end '--tw-shadow-colored': join(_).replace(/([^,]\s+)(?:#[a-f\d]+|(?:(?:hsl|rgb)a?|hwb|lab|lch|color|var)\(.+?\)|[a-z]+)(,|$)/g, '$1var(--tw-shadow-color)$2'), boxShadow: "var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)" })), // Opacity matchTheme('(opacity)-'), /*, 'opacity' */ // Mix Blend Mode match('mix-blend-', 'mixBlendMode'), /* FILTERS */...filter(), ...filter('backdrop-'), /* TRANSITIONS AND ANIMATION */ // Transition Property matchTheme('transition(?:$|-)', 'transitionProperty', (match, { theme }) => ({ transitionProperty: join(match), transitionTimingFunction: 'none' == match._ ? void 0 : join(theme('transitionTimingFunction', '')), transitionDuration: 'none' == match._ ? void 0 : join(theme('transitionDuration', '')) })), // Transition Duration matchTheme('duration(?:$|-)', 'transitionDuration', 'transitionDuration', join), // Transition Timing Function matchTheme('ease(?:$|-)', 'transitionTimingFunction', 'transitionTimingFunction', join), // Transition Delay matchTheme('delay(?:$|-)', 'transitionDelay', 'transitionDelay', join), matchTheme('animate(?:$|-)', 'animation', (match, { theme, h, e }) => { let animation = join(match), // Try to auto inject keyframes parts = animation.split(' '), keyframeValues = theme('keyframes', parts[0]); return keyframeValues ? { ['@keyframes ' + (parts[0] = e(h(parts[0])))]: keyframeValues, animation: parts.join(' ') } : { animation }; }), /* TRANSFORMS */ // Transform '(transform)-(none)', match('transform', tranformDefaults), match('transform-(cpu|gpu)', ({ 1: $1 }) => ({ '--tw-transform': transformValue('gpu' == $1) })), // Scale matchTheme('scale(-[xy])?-', 'scale', ({ 1: $1, _ }) => ({ ['--tw-scale' + ($1 || '-x')]: _, ['--tw-scale' + ($1 || '-y')]: _, ...tranformDefaults() })), // Rotate matchTheme('-?(rotate)-', 'rotate', transform), // Translate matchTheme('-?(translate-[xy])-', 'translate', transform), // Skew matchTheme('-?(skew-[xy])-', 'skew', transform), // Transform Origin match('origin-(center|((top|bottom)(-(left|right))?)|left|right)', 'transformOrigin', spacify), /* INTERACTIVITY */ // Appearance '(appearance)-', // Columns matchTheme('(columns)-'), /*, 'columns' */'(columns)-(\\d+)', // Break Before, After and Inside '(break-(?:before|after|inside))-', // Cursor matchTheme('(cursor)-'), /*, 'cursor' */'(cursor)-', // Scroll Snap Type match('snap-(none)', 'scroll-snap-type'), match('snap-(x|y|both)', ({ 1: $1 }) => ({ ...asDefaults({ '--tw-scroll-snap-strictness': 'proximity' }), 'scroll-snap-type': $1 + ' var(--tw-scroll-snap-strictness)' })), match('snap-(mandatory|proximity)', '--tw-scroll-snap-strictness'), // Scroll Snap Align match('snap-(?:(start|end|center)|align-(none))', 'scroll-snap-align'), // Scroll Snap Stop match('snap-(normal|always)', 'scroll-snap-stop'), match('scroll-(auto|smooth)', 'scroll-behavior'), // Scroll Margin // Padding matchTheme('scroll-p([xytrbl])?(?:$|-)', 'padding', edge('scroll-padding')), // Margin matchTheme('-?scroll-m([xytrbl])?(?:$|-)', 'scroll-margin', edge('scroll-margin')), // Touch Action match('touch-(auto|none|manipulation)', 'touch-action'), match('touch-(pinch-zoom|pan-(?:(x|left|right)|(y|up|down)))', ({ 1: $1, 2: $2, 3: $3 }) => ({ ...asDefaults({ '--tw-pan-x': 'var(--tw-empty,/*!*/ /*!*/)', '--tw-pan-y': 'var(--tw-empty,/*!*/ /*!*/)', '--tw-pinch-zoom': 'var(--tw-empty,/*!*/ /*!*/)', '--tw-touch-action': 'var(--tw-pan-x) var(--tw-pan-y) var(--tw-pinch-zoom)' }), // x, left, right -> pan-x // y, up, down -> pan-y // -> pinch-zoom [`--tw-${$2 ? 'pan-x' : $3 ? 'pan-y' : $1}`]: $1, 'touch-action': 'var(--tw-touch-action)' })), // Outline Style match('outline-none', { outline: '2px solid transparent', 'outline-offset': '2px' }), match('outline', { outlineStyle: 'solid' }), match('outline-(dashed|dotted|double)', 'outlineStyle'), // Outline Offset matchTheme('-?(outline-offset)-'), /*, 'outlineOffset'*/ // Outline Color matchColor('outline-', { opacityVariable: false, opacitySection: 'opacity' }), // Outline Width matchTheme('outline-', 'outlineWidth'), // Pointer Events '(pointer-events)-', // Will Change matchTheme('(will-change)-'), /*, 'willChange' */'(will-change)-', // Resize ['resize(?:-(none|x|y))?', 'resize', ({ 1: $1 }) => ({ x: 'horizontal', y: 'vertical' })[$1] || $1 || 'both'], // User Select match('select-(none|text|all|auto)', 'userSelect'), /* SVG */ // Fill, Stroke matchColor('fill-', { section: 'fill', opacityVariable: false, opacitySection: 'opacity' }), matchColor('stroke-', { section: 'stroke', opacityVariable: false, opacitySection: 'opacity' }), // Stroke Width matchTheme('stroke-', 'strokeWidth'), /* ACCESSIBILITY */ // Screen Readers match('sr-only', { position: 'absolute', width: '1px', height: '1px', padding: '0', margin: '-1px', overflow: 'hidden', whiteSpace: 'nowrap', clip: 'rect(0,0,0,0)', borderWidth: '0' }), match('not-sr-only', { position: 'static', width: 'auto', height: 'auto', padding: '0', margin: '0', overflow: 'visible', whiteSpace: 'normal', clip: 'auto' })]; function spacify(value) { return ('string' == typeof value ? value : value[1]).replace(/-/g, ' ').trim(); } function columnify(value) { return ('string' == typeof value ? value : value[1]).replace('col', 'column'); } function position(shorthand, separator = '-') { let longhand = []; for (let short of shorthand) longhand.push({ t: 'top', r: 'right', b: 'bottom', l: 'left' }[short]); return longhand.join(separator); } function join(value) { return value && '' + (value._ || value); } function convertContentValue({ $$ }) { return ({ // /* aut*/ o: '', /* sta*/ r: /*t*/'flex-', /* end*/'': 'flex-', // /* cen*/ t /*er*/: '', /* bet*/ w: /*een*/'space-', /* aro*/u: /*nd*/'space-', /* eve*/n: /*ly*/'space-' }[$$[3] || ''] || '') + $$; } function edge(propertyPrefix, propertySuffix = '') { return ({ 1: $1, _ }) => { let edges = { x: 'lr', y: 'tb' }[$1] || $1 + $1; return edges ? { ...toCSS(propertyPrefix + '-' + position(edges[0]) + propertySuffix, _), ...toCSS(propertyPrefix + '-' + position(edges[1]) + propertySuffix, _) } : toCSS(propertyPrefix + propertySuffix, _); }; } function filter(prefix = '') { let filters = ['blur', 'brightness', 'contrast', 'grayscale', 'hue-rotate', 'invert', prefix && 'opacity', 'saturate', 'sepia', !prefix && 'drop-shadow'].filter(Boolean), defaults = {}; // first create properties defaults for (let key of filters) defaults[`--tw-${prefix}${key}`] = 'var(--tw-empty,/*!*/ /*!*/)'; return defaults = { // move defaults ...asDefaults(defaults), // add default filter which allows standalone usage [`${prefix}filter`]: filters.map(key => `var(--tw-${prefix}${key})`).join(' ') }, [`(${prefix}filter)-(none)`, match(`${prefix}filter`, defaults), ...filters.map(key => matchTheme( // hue-rotate can be negated `${'h' == key[0] ? '-?' : ''}(${prefix}${key})(?:$|-)`, key, ({ 1: $1, _ }) => ({ [`--tw-${$1}`]: asArray(_).map(value => `${key}(${value})`).join(' '), ...defaults })))]; } function transform({ 1: $1, _ }) { return { ['--tw-' + $1]: _, ...tranformDefaults() }; } function tranformDefaults() { return { ...asDefaults({ '--tw-translate-x': '0', '--tw-translate-y': '0', '--tw-rotate': '0', '--tw-skew-x': '0', '--tw-skew-y': '0', '--tw-scale-x': '1', '--tw-scale-y': '1', '--tw-transform': transformValue() }), transform: 'var(--tw-transform)' }; } function transformValue(gpu) { return [gpu ? // -gpu 'translate3d(var(--tw-translate-x),var(--tw-translate-y),0)' : 'translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y))', 'rotate(var(--tw-rotate))', 'skewX(var(--tw-skew-x))', 'skewY(var(--tw-skew-y))', 'scaleX(var(--tw-scale-x))', 'scaleY(var(--tw-scale-y))'].join(' '); } function span({ 1: $1, 2: $2 }) { return `${$1} ${$2} / ${$1} ${$2}`; } function gridTemplate({ 1: $1 }) { return `repeat(${$1},minmax(0,1fr))`; } function asDefaults(props) { return { '@layer defaults': { '*,::before,::after': props, '::backdrop': props } }; } // indirection wrapper to remove autocomplete functions from production bundles let variants = [['sticky', '@supports ((position: -webkit-sticky) or (position:sticky))'], ['motion-reduce', '@media (prefers-reduced-motion:reduce)'], ['motion-safe', '@media (prefers-reduced-motion:no-preference)'], ['print', '@media print'], ['(portrait|landscape)', ({ 1: $1 }) => `@media (orientation:${$1})`], ['contrast-(more|less)', ({ 1: $1 }) => `@media (prefers-contrast:${$1})`], ['(first-(letter|line)|placeholder|backdrop|before|after)', ({ 1: $1 }) => `&::${$1}`], ['(marker|selection)', ({ 1: $1 }) => `& *::${$1},&::${$1}`], ['file', '&::file-selector-button'], ['(first|last|only)', ({ 1: $1 }) => `&:${$1}-child`], ['even', '&:nth-child(2n)'], ['odd', '&:nth-child(odd)'], ['open', '&[open]'], // All other pseudo classes are already supported by twind ['(aria|data)-', ({ 1: $1, /* aria or data */$$ }, /* everything after the dash */context) => $$ && `&[${$1}-${// aria-asc or data-checked -> from theme context.theme($1, $$) || // aria-[...] or data-[...] arbitrary($$, '', context) || // default handling `${$$}="true"`}]`], /* Styling based on parent and peer state */ // Groups classes like: group-focus and group-hover // these need to add a marker selector with the pseudo class // => '.group:focus .group-focus:selector' ['((group|peer)(~[^-[]+)?)(-\\[(.+)]|[-[].+?)(\\/.+)?', ({ 2: type, 3: name = '', 4: $4, 5: $5 = '', 6: label = name }, { e, h, v }) => { let selector = normalize($5) || ('[' == $4[0] ? $4 : v($4.slice(1))); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access return `${(selector.includes('&') ? selector : '&' + selector).replace(/&/g, `:merge(.${e(h(type + label))})`)}${'p' == type[0] ? '~' : ' '}&`; }], // direction variants ['(ltr|rtl)', ({ 1: $1 }) => `[dir="${$1}"] &`], ['supports-', ({ $$ }, /* everything after the dash */context) => { $$ && ($$ = context.theme('supports', $$) || arbitrary($$, '', context)); if ($$) return $$.includes(':') || ($$ += ':var(--tw)'), /^\w*\s*\(/.test($$) || ($$ = `(${$$})`), // Chrome has a bug where `(condtion1)or(condition2)` is not valid // But `(condition1) or (condition2)` is supported. `@supports ${$$.replace(/\b(and|or|not)\b/g, ' $1 ').trim()}`; }], ['max-', ({ $$ }, context) => { $$ && ($$ = context.theme('screens', $$) || arbitrary($$, '', context)); if ('string' == typeof $$) return `@media not all and (min-width:${$$})`; }], ['min-', ({ $$ }, context) => { return $$ && ($$ = arbitrary($$, '', context)), $$ && `@media (min-width:${$$})`; }], // Arbitrary variants [/^\[(.+)]$/, ({ 1: $1 }) => /[&@]/.test($1) && normalize($1).replace(/[}]+$/, '').split('{')]]; /** Allows to disable to tailwind preflight (default: `false` eg include the tailwind preflight ) */ /** * @experimental */ function presetTailwindBase({ colors, disablePreflight } = {}) { return { // allow other preflight to run preflight: disablePreflight ? void 0 : preflight, theme: { ...theme, colors: { inherit: 'inherit', current: 'currentColor', transparent: 'transparent', black: '#000', white: '#fff', ...colors } }, variants, rules, finalize(rule) { return ( // automatically add `content: ''` to before and after so you don’t have to specify it unless you want a different value // ignore global, preflight, and auto added rules rule.n && // only if there are declarations rule.d && // and it has a ::before or ::after selector rule.r.some(r => /^&::(before|after)$/.test(r)) && // there is no content property yet !/(^|;)content:/.test(rule.d) ? { ...rule, d: 'content:var(--tw-content);' + rule.d } : rule ); } }; } // Source from https://github.com/tailwindlabs/tailwindcss/blob/master/src/public/colors.js /** * @module @twind/preset-tailwind/colors */let slate = { 50: '#f8fafc', 100: '#f1f5f9', 200: '#e2e8f0', 300: '#cbd5e1', 400: '#94a3b8', 500: '#64748b', 600: '#475569', 700: '#334155', 800: '#1e293b', 900: '#0f172a' }, gray = { 50: '#f9fafb', 100: '#f3f4f6', 200: '#e5e7eb', 300: '#d1d5db', 400: '#9ca3af', 500: '#6b7280', 600: '#4b5563', 700: '#374151', 800: '#1f2937', 900: '#111827' }, zinc = { 50: '#fafafa', 100: '#f4f4f5', 200: '#e4e4e7', 300: '#d4d4d8', 400: '#a1a1aa', 500: '#71717a', 600: '#52525b', 700: '#3f3f46', 800: '#27272a', 900: '#18181b' }, neutral = { 50: '#fafafa', 100: '#f5f5f5', 200: '#e5e5e5', 300: '#d4d4d4', 400: '#a3a3a3', 500: '#737373', 600: '#525252', 700: '#404040', 800: '#262626', 900: '#171717' }, stone = { 50: '#fafaf9', 100: '#f5f5f4', 200: '#e7e5e4', 300: '#d6d3d1', 400: '#a8a29e', 500: '#78716c', 600: '#57534e', 700: '#44403c', 800: '#292524', 900: '#1c1917' }, red = { 50: '#fef2f2', 100: '#fee2e2', 200: '#fecaca', 300: '#fca5a5', 400: '#f87171', 500: '#ef4444', 600: '#dc2626', 700: '#b91c1c', 800: '#991b1b', 900: '#7f1d1d' }, orange = { 50: '#fff7ed', 100: '#ffedd5', 200: '#fed7aa', 300: '#fdba74', 400: '#fb923c', 500: '#f97316', 600: '#ea580c', 700: '#c2410c', 800: '#9a3412', 900: '#7c2d12' }, amber = { 50: '#fffbeb', 100: '#fef3c7', 200: '#fde68a', 300: '#fcd34d', 400: '#fbbf24', 500: '#f59e0b', 600: '#d97706', 700: '#b45309', 800: '#92400e', 900: '#78350f' }, yellow = { 50: '#fefce8', 100: '#fef9c3', 200: '#fef08a', 300: '#fde047', 400: '#facc15', 500: '#eab308', 600: '#ca8a04', 700: '#a16207', 800: '#854d0e', 900: '#713f12' }, lime = { 50: '#f7fee7', 100: '#ecfccb', 200: '#d9f99d', 300: '#bef264', 400: '#a3e635', 500: '#84cc16', 600: '#65a30d', 700: '#4d7c0f', 800: '#3f6212', 900: '#365314' }, green = { 50: '#f0fdf4', 100: '#dcfce7', 200: '#bbf7d0', 300: '#86efac', 400: '#4ade80', 500: '#22c55e', 600: '#16a34a', 700: '#15803d', 800: '#166534', 900: '#14532d' }, emerald = { 50: '#ecfdf5', 100: '#d1fae5', 200: '#a7f3d0', 300: '#6ee7b7', 400: '#34d399', 500: '#10b981', 600: '#059669', 700: '#047857', 800: '#065f46', 900: '#064e3b' }, teal = { 50: '#f0fdfa', 100: '#ccfbf1', 200: '#99f6e4', 300: '#5eead4', 400: '#2dd4bf', 500: '#14b8a6', 600: '#0d9488', 700: '#0f766e', 800: '#115e59', 900: '#134e4a' }, cyan = { 50: '#ecfeff', 100: '#cffafe', 200: '#a5f3fc', 300: '#67e8f9', 400: '#22d3ee', 500: '#06b6d4', 600: '#0891b2', 700: '#0e7490', 800: '#155e75', 900: '#164e63' }, sky = { 50: '#f0f9ff', 100: '#e0f2fe', 200: '#bae6fd', 300: '#7dd3fc', 400: '#38bdf8', 500: '#0ea5e9', 600: '#0284c7', 700: '#0369a1', 800: '#075985', 900: '#0c4a6e' }, blue = { 50: '#eff6ff', 100: '#dbeafe', 200: '#bfdbfe', 300: '#93c5fd', 400: '#60a5fa', 500: '#3b82f6', 600: '#2563eb', 700: '#1d4ed8', 800: '#1e40af', 900: '#1e3a8a' }, indigo = { 50: '#eef2ff', 100: '#e0e7ff', 200: '#c7d2fe', 300: '#a5b4fc', 400: '#818cf8', 500: '#6366f1', 600: '#4f46e5', 700: '#4338ca', 800: '#3730a3', 900: '#312e81' }, violet = { 50: '#f5f3ff', 100: '#ede9fe', 200: '#ddd6fe', 300: '#c4b5fd', 400: '#a78bfa', 500: '#8b5cf6', 600: '#7c3aed', 700: '#6d28d9', 800: '#5b21b6', 900: '#4c1d95' }, purple = { 50: '#faf5ff', 100: '#f3e8ff', 200: '#e9d5ff', 300: '#d8b4fe', 400: '#c084fc', 500: '#a855f7', 600: '#9333ea', 700: '#7e22ce', 800: '#6b21a8', 900: '#581c87' }, fuchsia = { 50: '#fdf4ff', 100: '#fae8ff', 200: '#f5d0fe', 300: '#f0abfc', 400: '#e879f9', 500: '#d946ef', 600: '#c026d3', 700: '#a21caf', 800: '#86198f', 900: '#701a75' }, pink = { 50: '#fdf2f8', 100: '#fce7f3', 200: '#fbcfe8', 300: '#f9a8d4', 400: '#f472b6', 500: '#ec4899', 600: '#db2777', 700: '#be185d', 800: '#9d174d', 900: '#831843' }, rose = { 50: '#fff1f2', 100: '#ffe4e6', 200: '#fecdd3', 300: '#fda4af', 400: '#fb7185', 500: '#f43f5e', 600: '#e11d48', 700: '#be123c', 800: '#9f1239', 900: '#881337' }, // get lightBlue() { // warn({ version: 'v2.2', from: 'lightBlue', to: 'sky' }) // return this.sky // } // get warmGray() { // warn({ version: 'v3.0', from: 'warmGray', to: 'stone' }) // return this.stone // } // get trueGray() { // warn({ version: 'v3.0', from: 'trueGray', to: 'neutral' }) // return this.neutral // } // get coolGray() { // warn({ version: 'v3.0', from: 'coolGray', to: 'gray' }) // return this.gray // } // get blueGray() { // warn({ version: 'v3.0', from: 'blueGray', to: 'slate' }) // return this.slate // } colors = { __proto__: null, slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose }; /** Allows to disable to tailwind preflight (default: `false` eg include the tailwind preflight ) */ function presetTailwind({ disablePreflight } = {}) { return presetTailwindBase({ colors, disablePreflight }); } const tw = twind({ preflight: false, hash: (className, defaultHash) => { return `tw-${defaultHash(className).slice(1)}`; }, presets: [presetAutoprefix(), presetTailwind({ disablePreflight: true })] }, dom()); const _tmpl$$c = /*#__PURE__*/template(`
edition, v