UNPKG

3d-grass-title

Version:

A customizable 3D grass-textured title web component using Lit + TypeScript + Three.js

684 lines (673 loc) 24.3 kB
import { css as Z, LitElement as V, html as K } from "lit"; import * as d from "three"; import { Loader as X, FileLoader as Q, ShapePath as Y } from "three"; /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ const tt = (i) => (t, e) => { e !== void 0 ? e.addInitializer(() => { customElements.define(i, t); }) : customElements.define(i, t); }; /** * @license * Copyright 2019 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ const F = globalThis, U = F.ShadowRoot && (F.ShadyCSS === void 0 || F.ShadyCSS.nativeShadow) && "adoptedStyleSheets" in Document.prototype && "replace" in CSSStyleSheet.prototype, j = Symbol(), D = /* @__PURE__ */ new WeakMap(); let et = class { constructor(t, e, s) { if (this._$cssResult$ = !0, s !== j) throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead."); this.cssText = t, this.t = e; } get styleSheet() { let t = this.o; const e = this.t; if (U && t === void 0) { const s = e !== void 0 && e.length === 1; s && (t = D.get(e)), t === void 0 && ((this.o = t = new CSSStyleSheet()).replaceSync(this.cssText), s && D.set(e, t)); } return t; } toString() { return this.cssText; } }; const st = (i) => new et(typeof i == "string" ? i : i + "", void 0, j), it = (i, t) => { if (U) i.adoptedStyleSheets = t.map((e) => e instanceof CSSStyleSheet ? e : e.styleSheet); else for (const e of t) { const s = document.createElement("style"), r = F.litNonce; r !== void 0 && s.setAttribute("nonce", r), s.textContent = e.cssText, i.appendChild(s); } }, L = U ? (i) => i : (i) => i instanceof CSSStyleSheet ? ((t) => { let e = ""; for (const s of t.cssRules) e += s.cssText; return st(e); })(i) : i; /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ const { is: rt, defineProperty: nt, getOwnPropertyDescriptor: ot, getOwnPropertyNames: at, getOwnPropertySymbols: ht, getPrototypeOf: lt } = Object, M = globalThis, k = M.trustedTypes, ct = k ? k.emptyScript : "", dt = M.reactiveElementPolyfillSupport, x = (i, t) => i, A = { toAttribute(i, t) { switch (t) { case Boolean: i = i ? ct : null; break; case Object: case Array: i = i == null ? i : JSON.stringify(i); } return i; }, fromAttribute(i, t) { let e = i; switch (t) { case Boolean: e = i !== null; break; case Number: e = i === null ? null : Number(i); break; case Object: case Array: try { e = JSON.parse(i); } catch { e = null; } } return e; } }, I = (i, t) => !rt(i, t), N = { attribute: !0, type: String, converter: A, reflect: !1, useDefault: !1, hasChanged: I }; Symbol.metadata ??= Symbol("metadata"), M.litPropertyMetadata ??= /* @__PURE__ */ new WeakMap(); class E extends HTMLElement { static addInitializer(t) { this._$Ei(), (this.l ??= []).push(t); } static get observedAttributes() { return this.finalize(), this._$Eh && [...this._$Eh.keys()]; } static createProperty(t, e = N) { if (e.state && (e.attribute = !1), this._$Ei(), this.prototype.hasOwnProperty(t) && ((e = Object.create(e)).wrapped = !0), this.elementProperties.set(t, e), !e.noAccessor) { const s = Symbol(), r = this.getPropertyDescriptor(t, s, e); r !== void 0 && nt(this.prototype, t, r); } } static getPropertyDescriptor(t, e, s) { const { get: r, set: o } = ot(this.prototype, t) ?? { get() { return this[e]; }, set(n) { this[e] = n; } }; return { get: r, set(n) { const a = r?.call(this); o?.call(this, n), this.requestUpdate(t, a, s); }, configurable: !0, enumerable: !0 }; } static getPropertyOptions(t) { return this.elementProperties.get(t) ?? N; } static _$Ei() { if (this.hasOwnProperty(x("elementProperties"))) return; const t = lt(this); t.finalize(), t.l !== void 0 && (this.l = [...t.l]), this.elementProperties = new Map(t.elementProperties); } static finalize() { if (this.hasOwnProperty(x("finalized"))) return; if (this.finalized = !0, this._$Ei(), this.hasOwnProperty(x("properties"))) { const e = this.properties, s = [...at(e), ...ht(e)]; for (const r of s) this.createProperty(r, e[r]); } const t = this[Symbol.metadata]; if (t !== null) { const e = litPropertyMetadata.get(t); if (e !== void 0) for (const [s, r] of e) this.elementProperties.set(s, r); } this._$Eh = /* @__PURE__ */ new Map(); for (const [e, s] of this.elementProperties) { const r = this._$Eu(e, s); r !== void 0 && this._$Eh.set(r, e); } this.elementStyles = this.finalizeStyles(this.styles); } static finalizeStyles(t) { const e = []; if (Array.isArray(t)) { const s = new Set(t.flat(1 / 0).reverse()); for (const r of s) e.unshift(L(r)); } else t !== void 0 && e.push(L(t)); return e; } static _$Eu(t, e) { const s = e.attribute; return s === !1 ? void 0 : typeof s == "string" ? s : typeof t == "string" ? t.toLowerCase() : void 0; } constructor() { super(), this._$Ep = void 0, this.isUpdatePending = !1, this.hasUpdated = !1, this._$Em = null, this._$Ev(); } _$Ev() { this._$ES = new Promise((t) => this.enableUpdating = t), this._$AL = /* @__PURE__ */ new Map(), this._$E_(), this.requestUpdate(), this.constructor.l?.forEach((t) => t(this)); } addController(t) { (this._$EO ??= /* @__PURE__ */ new Set()).add(t), this.renderRoot !== void 0 && this.isConnected && t.hostConnected?.(); } removeController(t) { this._$EO?.delete(t); } _$E_() { const t = /* @__PURE__ */ new Map(), e = this.constructor.elementProperties; for (const s of e.keys()) this.hasOwnProperty(s) && (t.set(s, this[s]), delete this[s]); t.size > 0 && (this._$Ep = t); } createRenderRoot() { const t = this.shadowRoot ?? this.attachShadow(this.constructor.shadowRootOptions); return it(t, this.constructor.elementStyles), t; } connectedCallback() { this.renderRoot ??= this.createRenderRoot(), this.enableUpdating(!0), this._$EO?.forEach((t) => t.hostConnected?.()); } enableUpdating(t) { } disconnectedCallback() { this._$EO?.forEach((t) => t.hostDisconnected?.()); } attributeChangedCallback(t, e, s) { this._$AK(t, s); } _$ET(t, e) { const s = this.constructor.elementProperties.get(t), r = this.constructor._$Eu(t, s); if (r !== void 0 && s.reflect === !0) { const o = (s.converter?.toAttribute !== void 0 ? s.converter : A).toAttribute(e, s.type); this._$Em = t, o == null ? this.removeAttribute(r) : this.setAttribute(r, o), this._$Em = null; } } _$AK(t, e) { const s = this.constructor, r = s._$Eh.get(t); if (r !== void 0 && this._$Em !== r) { const o = s.getPropertyOptions(r), n = typeof o.converter == "function" ? { fromAttribute: o.converter } : o.converter?.fromAttribute !== void 0 ? o.converter : A; this._$Em = r; const a = n.fromAttribute(e, o.type); this[r] = a ?? this._$Ej?.get(r) ?? a, this._$Em = null; } } requestUpdate(t, e, s) { if (t !== void 0) { const r = this.constructor, o = this[t]; if (s ??= r.getPropertyOptions(t), !((s.hasChanged ?? I)(o, e) || s.useDefault && s.reflect && o === this._$Ej?.get(t) && !this.hasAttribute(r._$Eu(t, s)))) return; this.C(t, e, s); } this.isUpdatePending === !1 && (this._$ES = this._$EP()); } C(t, e, { useDefault: s, reflect: r, wrapped: o }, n) { s && !(this._$Ej ??= /* @__PURE__ */ new Map()).has(t) && (this._$Ej.set(t, n ?? e ?? this[t]), o !== !0 || n !== void 0) || (this._$AL.has(t) || (this.hasUpdated || s || (e = void 0), this._$AL.set(t, e)), r === !0 && this._$Em !== t && (this._$Eq ??= /* @__PURE__ */ new Set()).add(t)); } async _$EP() { this.isUpdatePending = !0; try { await this._$ES; } catch (e) { Promise.reject(e); } const t = this.scheduleUpdate(); return t != null && await t, !this.isUpdatePending; } scheduleUpdate() { return this.performUpdate(); } performUpdate() { if (!this.isUpdatePending) return; if (!this.hasUpdated) { if (this.renderRoot ??= this.createRenderRoot(), this._$Ep) { for (const [r, o] of this._$Ep) this[r] = o; this._$Ep = void 0; } const s = this.constructor.elementProperties; if (s.size > 0) for (const [r, o] of s) { const { wrapped: n } = o, a = this[r]; n !== !0 || this._$AL.has(r) || a === void 0 || this.C(r, void 0, o, a); } } let t = !1; const e = this._$AL; try { t = this.shouldUpdate(e), t ? (this.willUpdate(e), this._$EO?.forEach((s) => s.hostUpdate?.()), this.update(e)) : this._$EM(); } catch (s) { throw t = !1, this._$EM(), s; } t && this._$AE(e); } willUpdate(t) { } _$AE(t) { this._$EO?.forEach((e) => e.hostUpdated?.()), this.hasUpdated || (this.hasUpdated = !0, this.firstUpdated(t)), this.updated(t); } _$EM() { this._$AL = /* @__PURE__ */ new Map(), this.isUpdatePending = !1; } get updateComplete() { return this.getUpdateComplete(); } getUpdateComplete() { return this._$ES; } shouldUpdate(t) { return !0; } update(t) { this._$Eq &&= this._$Eq.forEach((e) => this._$ET(e, this[e])), this._$EM(); } updated(t) { } firstUpdated(t) { } } E.elementStyles = [], E.shadowRootOptions = { mode: "open" }, E[x("elementProperties")] = /* @__PURE__ */ new Map(), E[x("finalized")] = /* @__PURE__ */ new Map(), dt?.({ ReactiveElement: E }), (M.reactiveElementVersions ??= []).push("2.1.1"); /** * @license * Copyright 2017 Google LLC * SPDX-License-Identifier: BSD-3-Clause */ const ut = { attribute: !0, type: String, converter: A, reflect: !1, hasChanged: I }, pt = (i = ut, t, e) => { const { kind: s, metadata: r } = e; let o = globalThis.litPropertyMetadata.get(r); if (o === void 0 && globalThis.litPropertyMetadata.set(r, o = /* @__PURE__ */ new Map()), s === "setter" && ((i = Object.create(i)).wrapped = !0), o.set(e.name, i), s === "accessor") { const { name: n } = e; return { set(a) { const h = t.get.call(this); t.set.call(this, a), this.requestUpdate(n, h, i); }, init(a) { return a !== void 0 && this.C(n, void 0, i, a), a; } }; } if (s === "setter") { const { name: n } = e; return function(a) { const h = this[n]; t.call(this, a), this.requestUpdate(n, h, i); }; } throw Error("Unsupported decorator location: " + s); }; function S(i) { return (t, e) => typeof e == "object" ? pt(i, t, e) : ((s, r, o) => { const n = r.hasOwnProperty(o); return r.constructor.createProperty(o, s), n ? Object.getOwnPropertyDescriptor(r, o) : void 0; })(i, t, e); } class mt extends X { constructor(t) { super(t); } load(t, e, s, r) { const o = this, n = new Q(this.manager); n.setPath(this.path), n.setRequestHeader(this.requestHeader), n.setWithCredentials(this.withCredentials), n.load(t, function(a) { const h = o.parse(JSON.parse(a)); e && e(h); }, s, r); } parse(t) { return new ft(t); } } class ft { constructor(t) { this.isFont = !0, this.type = "Font", this.data = t; } generateShapes(t, e = 100) { const s = [], r = gt(t, e, this.data); for (let o = 0, n = r.length; o < n; o++) s.push(...r[o].toShapes()); return s; } } function gt(i, t, e) { const s = Array.from(i), r = t / e.resolution, o = (e.boundingBox.yMax - e.boundingBox.yMin + e.underlineThickness) * r, n = []; let a = 0, h = 0; for (let y = 0; y < s.length; y++) { const m = s[y]; if (m === ` `) a = 0, h -= o; else { const f = yt(m, r, a, h, e); a += f.offsetX, n.push(f.path); } } return n; } function yt(i, t, e, s, r) { const o = r.glyphs[i] || r.glyphs["?"]; if (!o) { console.error('THREE.Font: character "' + i + '" does not exists in font family ' + r.familyName + "."); return; } const n = new Y(); let a, h, y, m, f, w, _, $; if (o.o) { const l = o._cachedOutline || (o._cachedOutline = o.o.split(" ")); for (let c = 0, P = l.length; c < P; ) switch (l[c++]) { case "m": a = l[c++] * t + e, h = l[c++] * t + s, n.moveTo(a, h); break; case "l": a = l[c++] * t + e, h = l[c++] * t + s, n.lineTo(a, h); break; case "q": y = l[c++] * t + e, m = l[c++] * t + s, f = l[c++] * t + e, w = l[c++] * t + s, n.quadraticCurveTo(f, w, y, m); break; case "b": y = l[c++] * t + e, m = l[c++] * t + s, f = l[c++] * t + e, w = l[c++] * t + s, _ = l[c++] * t + e, $ = l[c++] * t + s, n.bezierCurveTo(f, w, _, $, y, m); break; } } return { offsetX: o.ha * t, path: n }; } function vt(i, t = 500, e = 1, s) { const r = "Arial", n = document.createElement("canvas"), a = n.getContext("2d"), h = i.split(` `), y = h.sort((u, g) => g.length - u.length)[0].length, m = 100 * 0.7 * y, f = h.length * 100; n.width = m, n.height = f, a.font = `bold 100px ${r}`, a.fillStyle = "#2a9d8f", a.clearRect(0, 0, n.width, n.height), h.forEach((u, g) => { a.fillText(u, 0, (g + 0.8) * f / h.length); }); const w = [], _ = Math.max(1, Math.round(10 - t / 150)), $ = a.getImageData( 0, 0, n.width, n.height ); for (let u = 0; u < n.height; u += _) for (let g = 0; g < n.width; g += _) $.data[(g + u * n.width) * 4] > 0 && w.push({ x: g, y: u }); const l = new d.ConeGeometry( 0.02 * e, 0.08 * e, 8 ), c = new d.ShaderMaterial({ uniforms: { uTime: { value: 0 }, uColor: { value: new d.Color(4881497) }, // Will be updated by component uLightIntensity: { value: 1.5 }, // Will be updated by component uSpread: { value: 0 } // For click animation }, vertexShader: ` uniform float uTime; uniform float uSpread; varying vec3 vNormal; varying vec3 vPosition; void main() { vNormal = normalize(normalMatrix * normal); vPosition = position; vec3 pos = position; // Add subtle wind movement based on instance ID float windX = sin(uTime * 2.0 + float(gl_InstanceID) * 0.1) * 0.01; float windY = sin(uTime * 1.5 + float(gl_InstanceID) * 0.15) * 0.005; float windZ = cos(uTime * 1.8 + float(gl_InstanceID) * 0.05) * 0.003; pos.x += windX; pos.y += windY; pos.z += windZ; // Add spread effect for click animation vec3 spreadOffset = vec3( sin(float(gl_InstanceID) * 0.5) * uSpread * 5.0, cos(float(gl_InstanceID) * 0.3) * uSpread * 5.0, sin(float(gl_InstanceID) * 0.8) * uSpread * 2.0 ); vec4 mvPosition = modelViewMatrix * instanceMatrix * vec4(pos + spreadOffset, 1.0); gl_Position = projectionMatrix * mvPosition; } `, fragmentShader: ` uniform vec3 uColor; uniform float uLightIntensity; varying vec3 vNormal; varying vec3 vPosition; void main() { // Simple directional lighting vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0)); float NdotL = max(dot(normalize(vNormal), lightDir), 0.0); float diffuse = 0.3 + 0.7 * NdotL; // Ambient + diffuse // Apply lighting and intensity vec3 finalColor = uColor * diffuse * uLightIntensity; gl_FragColor = vec4(finalColor, 1.0); } ` }), P = w.length, b = new d.InstancedMesh( l, c, P ), O = s.boundingBox, z = (O.max.x - O.min.x) / (m * 0.8), C = new d.Matrix4(), R = new d.Color(); for (let u = 0; u < P; u++) { const g = w[u], q = (g.x - m / 2) * z, B = -(g.y - f / 2) * z, G = O.max.z + 0.05, H = Math.random() * Math.PI * 0.3, J = Math.random() * Math.PI * 2, W = Math.random() * Math.PI * 0.3, T = 0.8 + Math.random() * 0.4; C.makeRotationFromEuler( new d.Euler(H, J, W) ), C.scale(new d.Vector3(T, T, T)), C.setPosition(q, B, G), b.setMatrixAt(u, C), R.setHSL(0.25 + Math.random() * 0.05, 0.7, 0.3 + Math.random() * 0.2), b.setColorAt(u, R); } return b.instanceMatrix.needsUpdate = !0, b.instanceColor && (b.instanceColor.needsUpdate = !0), b; } var St = Object.defineProperty, wt = Object.getOwnPropertyDescriptor, v = (i, t, e, s) => { for (var r = s > 1 ? void 0 : s ? wt(t, e) : t, o = i.length - 1, n; o >= 0; o--) (n = i[o]) && (r = (s ? n(t, e, r) : n(r)) || r); return s && r && St(t, e, r), r; }; let p = class extends V { constructor() { super(...arguments), this.text = "Welcome", this.color = "#c5e194", this.lightIntensity = 1.2, this.rotation = [0, 0, 0], this.cameraDistance = 10, this.grassDensity = 800, this.grassHeight = 1.2, this.isAnimating = !1, this.animateScene = () => { this.animationId = requestAnimationFrame(this.animateScene); const i = performance.now() * 1e-3; if (this.grassField && this.grassField.material) { const t = this.grassField.material; t.uniforms && t.uniforms.uTime && (t.uniforms.uTime.value = i); } this.renderer.render(this.scene, this.camera); }, this.handleClick = () => { !this.link || this.isAnimating || (this.isAnimating = !0, this.startParticleSpreadAnimation()); }, this.startParticleSpreadAnimation = () => { if (!this.grassField || !this.grassField.material) return; const t = this.grassField.material.uniforms; if (t.uSpread) { const e = performance.now(), s = 800, r = () => { const o = performance.now() - e, n = Math.min(o / s, 1), a = 1 - Math.pow(1 - n, 3); t.uSpread.value = a, n < 1 ? requestAnimationFrame(r) : setTimeout(() => { this.startParticleReturnAnimation(); }, 200); }; r(); } }, this.startParticleReturnAnimation = () => { if (!this.grassField || !this.grassField.material) return; const t = this.grassField.material.uniforms; if (t.uSpread) { const e = performance.now(), s = 600, r = () => { const o = performance.now() - e, n = Math.min(o / s, 1), a = 1 - Math.pow(1 - n, 2); t.uSpread.value = 1 - a, n < 1 ? requestAnimationFrame(r) : (this.isAnimating = !1, this.link && (window.location.href = this.link)); }; r(); } }; } render() { return K`<canvas @click="${this.handleClick}"></canvas>`; } firstUpdated() { this.canvas = this.shadowRoot.querySelector("canvas"), this.initThreeJS(), this.loadFont(), this.setupResizeObserver(); } disconnectedCallback() { super.disconnectedCallback(), this.animationId && cancelAnimationFrame(this.animationId), this.resizeObserver && this.resizeObserver.disconnect(), this.cleanup(); } initThreeJS() { this.scene = new d.Scene(), this.scene.background = new d.Color(0); const i = this.canvas.getBoundingClientRect(); this.camera = new d.PerspectiveCamera( 75, i.width / i.height, 0.1, 1e3 ), this.camera.position.set(0, 0, this.cameraDistance), this.renderer = new d.WebGLRenderer({ canvas: this.canvas, antialias: !0, alpha: !0 }), this.renderer.setSize(i.width, i.height), this.renderer.setPixelRatio(window.devicePixelRatio), this.light = new d.DirectionalLight(16777215, this.lightIntensity), this.light.position.set(1, 1, 1), this.scene.add(this.light); const t = new d.AmbientLight(4210752, 0.4); this.scene.add(t); } loadFont() { this.fontLoader = new mt(); const i = this.fontUrl || "https://threejs.org/examples/fonts/helvetiker_regular.typeface.json"; this.fontLoader.load( i, async (t) => { this.font = t, await this.createGrassField(), this.animationId || this.animateScene(); }, void 0, async (t) => { console.error("Font loading error:", t), this.animationId || this.animateScene(); } ); } async createGrassField() { this.grassField && (this.scene.remove(this.grassField), this.grassField.geometry.dispose(), this.grassField.material && (Array.isArray(this.grassField.material) ? this.grassField.material.forEach((t) => t.dispose()) : this.grassField.material.dispose())); const i = this.scene.children.find( (t) => t.userData.isTextMesh ); i && this.scene.remove(i); try { const { TextGeometry: t } = await import("./TextGeometry-Cb4kkJR_.js"), e = new t(this.text, { font: this.font, size: 1, height: 0.5, curveSegments: 12, bevelEnabled: !0, bevelThickness: 0.1, bevelSize: 0.05, bevelOffset: 0, bevelSegments: 5 }); e.computeBoundingBox(); const s = -0.5 * (e.boundingBox.max.x - e.boundingBox.min.x), r = -0.5 * (e.boundingBox.max.y - e.boundingBox.min.y); if (e.translate(s, r, 0), this.grassField = vt( this.text, this.grassDensity, this.grassHeight, e ), this.scene.add(this.grassField), this.grassField.material instanceof d.ShaderMaterial) { const n = this.grassField.material.uniforms; n.uColor && (n.uColor.value = new d.Color(this.color)), n.uLightIntensity && (n.uLightIntensity.value = this.lightIntensity); } } catch (t) { console.error("Error creating grass text:", t); } } setupResizeObserver() { this.resizeObserver = new ResizeObserver(() => { this.handleResize(); }), this.resizeObserver.observe(this); } handleResize() { const i = this.canvas.getBoundingClientRect(); this.camera.aspect = i.width / i.height, this.camera.updateProjectionMatrix(), this.renderer.setSize(i.width, i.height); } cleanup() { this.grassField && (this.scene.remove(this.grassField), this.grassField.geometry.dispose(), this.grassField.material && (Array.isArray(this.grassField.material) ? this.grassField.material.forEach((i) => i.dispose()) : this.grassField.material.dispose())), this.renderer && this.renderer.dispose(); } updated(i) { if (i.has("text") && this.font && this.createGrassField(), (i.has("grassDensity") || i.has("grassHeight")) && this.font && this.createGrassField(), i.has("color") && this.grassField && this.grassField.material) { const e = this.grassField.material.uniforms; e.uColor && (e.uColor.value = new d.Color(this.color)); } if (i.has("lightIntensity") && (this.light && (this.light.intensity = this.lightIntensity), this.grassField && this.grassField.material)) { const e = this.grassField.material.uniforms; e.uLightIntensity && (e.uLightIntensity.value = this.lightIntensity); } i.has("rotation") && this.grassField && this.grassField.rotation.set( this.rotation[0], this.rotation[1], this.rotation[2] ), i.has("cameraDistance") && this.camera && this.camera.position.setZ(this.cameraDistance), i.has("fontUrl") && this.loadFont(); } }; p.styles = Z` :host { display: block; width: 100%; height: 25rem; position: relative; } canvas { width: 100%; height: 100%; display: block; cursor: pointer; } `; v([ S({ type: String, reflect: !0 }) ], p.prototype, "text", 2); v([ S({ type: String, reflect: !0 }) ], p.prototype, "color", 2); v([ S({ type: Number, reflect: !0, attribute: "light-intensity" }) ], p.prototype, "lightIntensity", 2); v([ S({ type: Array, converter: { fromAttribute: (i) => { try { return JSON.parse(i); } catch { return [0, 0, 0]; } }, toAttribute: (i) => JSON.stringify(i) } }) ], p.prototype, "rotation", 2); v([ S({ type: Number, reflect: !0, attribute: "camera-distance" }) ], p.prototype, "cameraDistance", 2); v([ S({ type: String, reflect: !0, attribute: "font-url" }) ], p.prototype, "fontUrl", 2); v([ S({ type: Number, reflect: !0, attribute: "grass-density" }) ], p.prototype, "grassDensity", 2); v([ S({ type: Number, reflect: !0, attribute: "grass-height" }) ], p.prototype, "grassHeight", 2); v([ S({ type: String, reflect: !0 }) ], p.prototype, "link", 2); p = v([ tt("grass-title") ], p); export { p as GrassTitle, vt as createGrassFieldFromTextCanvas };