Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoSign in
Socket

@github/text-expander-element

Package Overview
Dependencies
Maintainers
19
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@github/text-expander-element - npm Package Compare versions

Comparing version
2.9.1
to
2.9.2
+62
-83
dist/bundle.js

@@ -215,11 +215,2 @@ const ctrlBindings = !!navigator.userAgent.match(/Macintosh/);

/**
* A custom element is implemented as a class which extends HTMLElement (in the
* case of autonomous elements) or the interface you want to customize (in the
* case of customized built-in elements).
* @see https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks
*/
class CustomHTMLElement extends HTMLElement {
}
class InputStyleCloneUpdateEvent extends Event {

@@ -232,3 +223,3 @@ constructor() {

/**
* Create an element that exactly matches an input pixel-for-pixel and automatically stays in sync with it. This
* Creates an element that exactly matches an input pixel-for-pixel and automatically stays in sync with it. This
* is a non-interactive overlay on to the input and can be used to affect the visual appearance of the input

@@ -250,3 +241,3 @@ * without modifying its behavior. The clone element is hidden by default.

// - koddsson/textarea-caret-position (Copyright (c) 2015 Jonathan Ong me@jongleberry.com): https://github.com/koddsson/textarea-caret-position/blob/eba40ec8488eed4d77815f109af22e1d9c0751d3/index.js
class InputStyleCloneElement extends CustomHTMLElement {
class InputStyleClone extends EventTarget {
#styleObserver = new MutationObserver(() => this.#updateStyles());

@@ -259,10 +250,11 @@ #resizeObserver = new ResizeObserver(() => this.#requestUpdateLayout());

#inputRef;
#container;
#container = document.createElement("div");
#cloneElement = document.createElement("div");
/**
* Get the clone for an input, reusing an existing one if available. This avoids creating unecessary clones, which
* have a performance cost due to their high-frequency event-based updates. Because these elements are shared, they
* should be mutated with caution.
* should be mutated with caution. If you're planning to mutate the clone, consider constructing a new one instead.
*
* Upon initial creation the clone element will automatically be inserted into the DOM and begin observing the
* linked input. Only one clone per input can ever exist at a time.
* linked input.
* @param input The target input to clone.

@@ -273,4 +265,3 @@ */

if (!clone) {
clone = new InputStyleCloneElement();
clone.connect(input);
clone = new InputStyleClone(input);
CloneRegistry.set(input, clone);

@@ -283,17 +274,50 @@ }

*
* NOTE: calling the static `for` method is nearly always preferable as it will reuse an existing clone if available.
* NOTE: calling the static `for` method is usually preferable as it will reuse an existing clone if available.
* However, if reusing clones is problematic (ie, if the clone needs to be mutated), a clone can be constructed
* directly with `new InputStyleCloneElement()` and then bound to an input and inserted into the DOM with
* `clone.connect(target)`.
* directly with `new InputStyleClone(target)`.
*/
connect(input) {
constructor(input) {
super();
this.#inputRef = new WeakRef(input);
// We want position:absolute so it doesn't take space in the layout, but that doesn't work with display:table-cell
// used in the HTMLInputElement approach. So we need a wrapper.
this.#container = document.createElement("div");
this.#container.style.position = "absolute";
this.#container.style.pointerEvents = "none";
this.#container.setAttribute("aria-hidden", "true");
this.#container.appendChild(this.#cloneElement);
this.#cloneElement.style.pointerEvents = "none";
this.#cloneElement.style.userSelect = "none";
this.#cloneElement.style.overflow = "hidden";
this.#cloneElement.style.display = "block";
// Important not to use display:none which would not render the content at all
this.#cloneElement.style.visibility = "hidden";
if (input instanceof HTMLTextAreaElement) {
this.#cloneElement.style.whiteSpace = "pre-wrap";
this.#cloneElement.style.wordWrap = "break-word";
}
else {
this.#cloneElement.style.whiteSpace = "nowrap";
// text in single-line inputs is vertically centered
this.#cloneElement.style.display = "table-cell";
this.#cloneElement.style.verticalAlign = "middle";
}
input.after(this.#container);
this.#container.appendChild(this);
this.#updateStyles();
this.#updateText();
this.#styleObserver.observe(input, {
attributeFilter: [
"style",
"dir", // users can right-click in some browsers to change the text direction dynamically
],
});
this.#resizeObserver.observe(input);
document.addEventListener("scroll", this.#onDocumentScrollOrResize, { capture: true });
window.addEventListener("resize", this.#onDocumentScrollOrResize, { capture: true });
// capture so this happens first, so other things can respond to `input` events after this data updates
input.addEventListener("input", this.#onInput, { capture: true });
}
/** Get the clone element. */
get element() {
return this.#cloneElement;
}
/**

@@ -307,39 +331,3 @@ * Force a recalculation. Will emit an `update` event. This is typically not needed unless the input has changed in

}
/** @private */
connectedCallback() {
this.#usingInput((input) => {
this.style.pointerEvents = "none";
this.style.userSelect = "none";
this.style.overflow = "hidden";
this.style.display = "block";
// Important not to use display:none which would not render the content at all
this.style.visibility = "hidden";
if (input instanceof HTMLTextAreaElement) {
this.style.whiteSpace = "pre-wrap";
this.style.wordWrap = "break-word";
}
else {
this.style.whiteSpace = "nowrap";
// text in single-line inputs is vertically centered
this.style.display = "table-cell";
this.style.verticalAlign = "middle";
}
this.setAttribute("aria-hidden", "true");
this.#updateStyles();
this.#updateText();
this.#styleObserver.observe(input, {
attributeFilter: [
"style",
"dir", // users can right-click in some browsers to change the text direction dynamically
],
});
this.#resizeObserver.observe(input);
document.addEventListener("scroll", this.#onDocumentScrollOrResize, { capture: true });
window.addEventListener("resize", this.#onDocumentScrollOrResize, { capture: true });
// capture so this happens first, so other things can respond to `input` events after this data updates
input.addEventListener("input", this.#onInput, { capture: true });
});
}
/** @private */
disconnectedCallback() {
disconnect() {
this.#container?.remove();

@@ -365,3 +353,3 @@ this.#styleObserver.disconnect();

if (!input)
return this.remove();
return this.disconnect();
return fn(input);

@@ -381,17 +369,17 @@ }

const inputStyle = window.getComputedStyle(input);
this.style.height = inputStyle.height;
this.style.width = inputStyle.width;
this.#cloneElement.style.height = inputStyle.height;
this.#cloneElement.style.width = inputStyle.width;
// Immediately re-adjust for browser inconsistencies in scrollbar handling, if necessary
if (input.clientHeight !== this.clientHeight)
this.style.height = `calc(${inputStyle.height} + ${input.clientHeight - this.clientHeight}px)`;
if (input.clientWidth !== this.clientWidth)
this.style.width = `calc(${inputStyle.width} + ${input.clientWidth - this.clientWidth}px)`;
if (input.clientHeight !== this.#cloneElement.clientHeight)
this.#cloneElement.style.height = `calc(${inputStyle.height} + ${input.clientHeight - this.#cloneElement.clientHeight}px)`;
if (input.clientWidth !== this.#cloneElement.clientWidth)
this.#cloneElement.style.width = `calc(${inputStyle.width} + ${input.clientWidth - this.#cloneElement.clientWidth}px)`;
// Position on top of the input
const inputRect = input.getBoundingClientRect();
const cloneRect = this.getBoundingClientRect();
const cloneRect = this.#cloneElement.getBoundingClientRect();
this.#xOffset = this.#xOffset + inputRect.left - cloneRect.left;
this.#yOffset = this.#yOffset + inputRect.top - cloneRect.top;
this.style.transform = `translate(${this.#xOffset}px, ${this.#yOffset}px)`;
this.scrollTop = input.scrollTop;
this.scrollLeft = input.scrollLeft;
this.#cloneElement.style.transform = `translate(${this.#xOffset}px, ${this.#yOffset}px)`;
this.#cloneElement.scrollTop = input.scrollTop;
this.#cloneElement.scrollLeft = input.scrollLeft;
this.dispatchEvent(new InputStyleCloneUpdateEvent());

@@ -416,3 +404,3 @@ });

for (const prop of propertiesToCopy)
this.style[prop] = inputStyle[prop];
this.#cloneElement.style[prop] = inputStyle[prop];
this.#requestUpdateLayout();

@@ -427,3 +415,3 @@ });

this.#usingInput((input) => {
this.textContent = input.value;
this.#cloneElement.textContent = input.value;
// This is often unecessary on a pure text update, but text updates could potentially cause layout updates like

@@ -483,11 +471,2 @@ // scrolling or resizing. And we run the update on _every frame_ when scrolling, so this isn't that expensive.

];
// Inspired by https://github.com/github/catalyst/blob/dc284dcf4f82329a9cac5c867462a8fa529b6c40/src/register.ts
try {
customElements.define("input-style-clone", InputStyleCloneElement);
}
catch (e) {
// Throws DOMException with NotSupportedError if already defined
if (!(e instanceof DOMException && e.name === "NotSupportedError"))
throw e;
}

@@ -598,3 +577,3 @@ class InputRange {

get #styleClone() {
return InputStyleCloneElement.for(this.#inputElement);
return InputStyleClone.for(this.#inputElement);
}

@@ -612,3 +591,3 @@ get #cloneElement() {

const range = document.createRange();
const textNode = this.#cloneElement.childNodes[0];
const textNode = this.#cloneElement.element.childNodes[0];
if (textNode) {

@@ -615,0 +594,0 @@ range.setStart(textNode, this.startOffset);

@@ -45,11 +45,2 @@ import Combobox from '@github/combobox-nav';

/**
* A custom element is implemented as a class which extends HTMLElement (in the
* case of autonomous elements) or the interface you want to customize (in the
* case of customized built-in elements).
* @see https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements#custom_element_lifecycle_callbacks
*/
class CustomHTMLElement extends HTMLElement {
}
class InputStyleCloneUpdateEvent extends Event {

@@ -62,3 +53,3 @@ constructor() {

/**
* Create an element that exactly matches an input pixel-for-pixel and automatically stays in sync with it. This
* Creates an element that exactly matches an input pixel-for-pixel and automatically stays in sync with it. This
* is a non-interactive overlay on to the input and can be used to affect the visual appearance of the input

@@ -80,3 +71,3 @@ * without modifying its behavior. The clone element is hidden by default.

// - koddsson/textarea-caret-position (Copyright (c) 2015 Jonathan Ong me@jongleberry.com): https://github.com/koddsson/textarea-caret-position/blob/eba40ec8488eed4d77815f109af22e1d9c0751d3/index.js
class InputStyleCloneElement extends CustomHTMLElement {
class InputStyleClone extends EventTarget {
#styleObserver = new MutationObserver(() => this.#updateStyles());

@@ -89,10 +80,11 @@ #resizeObserver = new ResizeObserver(() => this.#requestUpdateLayout());

#inputRef;
#container;
#container = document.createElement("div");
#cloneElement = document.createElement("div");
/**
* Get the clone for an input, reusing an existing one if available. This avoids creating unecessary clones, which
* have a performance cost due to their high-frequency event-based updates. Because these elements are shared, they
* should be mutated with caution.
* should be mutated with caution. If you're planning to mutate the clone, consider constructing a new one instead.
*
* Upon initial creation the clone element will automatically be inserted into the DOM and begin observing the
* linked input. Only one clone per input can ever exist at a time.
* linked input.
* @param input The target input to clone.

@@ -103,4 +95,3 @@ */

if (!clone) {
clone = new InputStyleCloneElement();
clone.connect(input);
clone = new InputStyleClone(input);
CloneRegistry.set(input, clone);

@@ -113,17 +104,50 @@ }

*
* NOTE: calling the static `for` method is nearly always preferable as it will reuse an existing clone if available.
* NOTE: calling the static `for` method is usually preferable as it will reuse an existing clone if available.
* However, if reusing clones is problematic (ie, if the clone needs to be mutated), a clone can be constructed
* directly with `new InputStyleCloneElement()` and then bound to an input and inserted into the DOM with
* `clone.connect(target)`.
* directly with `new InputStyleClone(target)`.
*/
connect(input) {
constructor(input) {
super();
this.#inputRef = new WeakRef(input);
// We want position:absolute so it doesn't take space in the layout, but that doesn't work with display:table-cell
// used in the HTMLInputElement approach. So we need a wrapper.
this.#container = document.createElement("div");
this.#container.style.position = "absolute";
this.#container.style.pointerEvents = "none";
this.#container.setAttribute("aria-hidden", "true");
this.#container.appendChild(this.#cloneElement);
this.#cloneElement.style.pointerEvents = "none";
this.#cloneElement.style.userSelect = "none";
this.#cloneElement.style.overflow = "hidden";
this.#cloneElement.style.display = "block";
// Important not to use display:none which would not render the content at all
this.#cloneElement.style.visibility = "hidden";
if (input instanceof HTMLTextAreaElement) {
this.#cloneElement.style.whiteSpace = "pre-wrap";
this.#cloneElement.style.wordWrap = "break-word";
}
else {
this.#cloneElement.style.whiteSpace = "nowrap";
// text in single-line inputs is vertically centered
this.#cloneElement.style.display = "table-cell";
this.#cloneElement.style.verticalAlign = "middle";
}
input.after(this.#container);
this.#container.appendChild(this);
this.#updateStyles();
this.#updateText();
this.#styleObserver.observe(input, {
attributeFilter: [
"style",
"dir", // users can right-click in some browsers to change the text direction dynamically
],
});
this.#resizeObserver.observe(input);
document.addEventListener("scroll", this.#onDocumentScrollOrResize, { capture: true });
window.addEventListener("resize", this.#onDocumentScrollOrResize, { capture: true });
// capture so this happens first, so other things can respond to `input` events after this data updates
input.addEventListener("input", this.#onInput, { capture: true });
}
/** Get the clone element. */
get element() {
return this.#cloneElement;
}
/**

@@ -137,39 +161,3 @@ * Force a recalculation. Will emit an `update` event. This is typically not needed unless the input has changed in

}
/** @private */
connectedCallback() {
this.#usingInput((input) => {
this.style.pointerEvents = "none";
this.style.userSelect = "none";
this.style.overflow = "hidden";
this.style.display = "block";
// Important not to use display:none which would not render the content at all
this.style.visibility = "hidden";
if (input instanceof HTMLTextAreaElement) {
this.style.whiteSpace = "pre-wrap";
this.style.wordWrap = "break-word";
}
else {
this.style.whiteSpace = "nowrap";
// text in single-line inputs is vertically centered
this.style.display = "table-cell";
this.style.verticalAlign = "middle";
}
this.setAttribute("aria-hidden", "true");
this.#updateStyles();
this.#updateText();
this.#styleObserver.observe(input, {
attributeFilter: [
"style",
"dir", // users can right-click in some browsers to change the text direction dynamically
],
});
this.#resizeObserver.observe(input);
document.addEventListener("scroll", this.#onDocumentScrollOrResize, { capture: true });
window.addEventListener("resize", this.#onDocumentScrollOrResize, { capture: true });
// capture so this happens first, so other things can respond to `input` events after this data updates
input.addEventListener("input", this.#onInput, { capture: true });
});
}
/** @private */
disconnectedCallback() {
disconnect() {
this.#container?.remove();

@@ -195,3 +183,3 @@ this.#styleObserver.disconnect();

if (!input)
return this.remove();
return this.disconnect();
return fn(input);

@@ -211,17 +199,17 @@ }

const inputStyle = window.getComputedStyle(input);
this.style.height = inputStyle.height;
this.style.width = inputStyle.width;
this.#cloneElement.style.height = inputStyle.height;
this.#cloneElement.style.width = inputStyle.width;
// Immediately re-adjust for browser inconsistencies in scrollbar handling, if necessary
if (input.clientHeight !== this.clientHeight)
this.style.height = `calc(${inputStyle.height} + ${input.clientHeight - this.clientHeight}px)`;
if (input.clientWidth !== this.clientWidth)
this.style.width = `calc(${inputStyle.width} + ${input.clientWidth - this.clientWidth}px)`;
if (input.clientHeight !== this.#cloneElement.clientHeight)
this.#cloneElement.style.height = `calc(${inputStyle.height} + ${input.clientHeight - this.#cloneElement.clientHeight}px)`;
if (input.clientWidth !== this.#cloneElement.clientWidth)
this.#cloneElement.style.width = `calc(${inputStyle.width} + ${input.clientWidth - this.#cloneElement.clientWidth}px)`;
// Position on top of the input
const inputRect = input.getBoundingClientRect();
const cloneRect = this.getBoundingClientRect();
const cloneRect = this.#cloneElement.getBoundingClientRect();
this.#xOffset = this.#xOffset + inputRect.left - cloneRect.left;
this.#yOffset = this.#yOffset + inputRect.top - cloneRect.top;
this.style.transform = `translate(${this.#xOffset}px, ${this.#yOffset}px)`;
this.scrollTop = input.scrollTop;
this.scrollLeft = input.scrollLeft;
this.#cloneElement.style.transform = `translate(${this.#xOffset}px, ${this.#yOffset}px)`;
this.#cloneElement.scrollTop = input.scrollTop;
this.#cloneElement.scrollLeft = input.scrollLeft;
this.dispatchEvent(new InputStyleCloneUpdateEvent());

@@ -246,3 +234,3 @@ });

for (const prop of propertiesToCopy)
this.style[prop] = inputStyle[prop];
this.#cloneElement.style[prop] = inputStyle[prop];
this.#requestUpdateLayout();

@@ -257,3 +245,3 @@ });

this.#usingInput((input) => {
this.textContent = input.value;
this.#cloneElement.textContent = input.value;
// This is often unecessary on a pure text update, but text updates could potentially cause layout updates like

@@ -313,11 +301,2 @@ // scrolling or resizing. And we run the update on _every frame_ when scrolling, so this isn't that expensive.

];
// Inspired by https://github.com/github/catalyst/blob/dc284dcf4f82329a9cac5c867462a8fa529b6c40/src/register.ts
try {
customElements.define("input-style-clone", InputStyleCloneElement);
}
catch (e) {
// Throws DOMException with NotSupportedError if already defined
if (!(e instanceof DOMException && e.name === "NotSupportedError"))
throw e;
}

@@ -428,3 +407,3 @@ class InputRange {

get #styleClone() {
return InputStyleCloneElement.for(this.#inputElement);
return InputStyleClone.for(this.#inputElement);
}

@@ -442,3 +421,3 @@ get #cloneElement() {

const range = document.createRange();
const textNode = this.#cloneElement.childNodes[0];
const textNode = this.#cloneElement.element.childNodes[0];
if (textNode) {

@@ -445,0 +424,0 @@ range.setStart(textNode, this.startOffset);

{
"name": "@github/text-expander-element",
"version": "2.9.1",
"version": "2.9.2",
"description": "Activates a suggestion menu to expand text snippets as you type.",

@@ -33,3 +33,3 @@ "repository": "github/text-expander-element",

"@github/combobox-nav": "^2.0.2",
"dom-input-range": "^1.2.0"
"dom-input-range": "^2.0.0"
},

@@ -36,0 +36,0 @@ "devDependencies": {