@rogieking/figui3 9.4.0 → 9.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/skills/figui3/components.md +2 -0
- package/CHANGELOG.md +21 -0
- package/README.md +28 -0
- package/components.css +6 -14
- package/dist/components.css +1 -1
- package/dist/fig.css +1 -1
- package/dist/fig.js +5 -5
- package/fig.js +106 -23
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -1934,31 +1934,58 @@ figDefineElement("fig-tooltip", FigTooltip);
|
|
|
1934
1934
|
|
|
1935
1935
|
/* Text Truncation */
|
|
1936
1936
|
class FigTruncate extends HTMLElement {
|
|
1937
|
-
static observedAttributes = ["position", "tail"];
|
|
1937
|
+
static observedAttributes = ["position", "tail", "tooltip"];
|
|
1938
1938
|
|
|
1939
1939
|
#originalText = null;
|
|
1940
1940
|
#boundEnter = null;
|
|
1941
1941
|
#boundLeave = null;
|
|
1942
|
+
#observer = null;
|
|
1942
1943
|
|
|
1943
1944
|
connectedCallback() {
|
|
1944
1945
|
this.#originalText = this.textContent;
|
|
1946
|
+
this.#observer ??= new MutationObserver(() => {
|
|
1947
|
+
this.#originalText = this.textContent;
|
|
1948
|
+
this.#render();
|
|
1949
|
+
});
|
|
1950
|
+
this.#observe();
|
|
1945
1951
|
figNextFrame(this, () => {
|
|
1946
1952
|
this.#render();
|
|
1953
|
+
this.#teardownTooltip();
|
|
1947
1954
|
this.#setupTooltip();
|
|
1948
1955
|
});
|
|
1949
1956
|
}
|
|
1950
1957
|
|
|
1951
1958
|
disconnectedCallback() {
|
|
1959
|
+
this.#observer?.disconnect();
|
|
1952
1960
|
this.#teardownTooltip();
|
|
1953
1961
|
}
|
|
1954
1962
|
|
|
1955
1963
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
1956
1964
|
if (oldValue === newValue) return;
|
|
1957
1965
|
if (this.#originalText === null) return;
|
|
1966
|
+
if (name === "tooltip") {
|
|
1967
|
+
this.#teardownTooltip();
|
|
1968
|
+
if (this.isConnected) this.#setupTooltip();
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1958
1971
|
this.#render();
|
|
1959
1972
|
}
|
|
1960
1973
|
|
|
1974
|
+
#observe() {
|
|
1975
|
+
this.#observer?.observe(this, {
|
|
1976
|
+
childList: true,
|
|
1977
|
+
characterData: true,
|
|
1978
|
+
subtree: true,
|
|
1979
|
+
});
|
|
1980
|
+
}
|
|
1981
|
+
|
|
1961
1982
|
#render() {
|
|
1983
|
+
this.#observer?.disconnect();
|
|
1984
|
+
this.#renderContent();
|
|
1985
|
+
if (this.isConnected) this.#observe();
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
#renderContent() {
|
|
1962
1989
|
const position = this.getAttribute("position") || "right";
|
|
1963
1990
|
const text = this.#originalText || "";
|
|
1964
1991
|
if (position === "middle") {
|
|
@@ -1991,7 +2018,7 @@ class FigTruncate extends HTMLElement {
|
|
|
1991
2018
|
)
|
|
1992
2019
|
return;
|
|
1993
2020
|
this.#boundEnter = () => {
|
|
1994
|
-
if (this
|
|
2021
|
+
if (!this.#isTruncated()) return;
|
|
1995
2022
|
FigTooltip.show(this, this.#originalText);
|
|
1996
2023
|
};
|
|
1997
2024
|
this.#boundLeave = () => {
|
|
@@ -2001,11 +2028,21 @@ class FigTruncate extends HTMLElement {
|
|
|
2001
2028
|
this.addEventListener("pointerleave", this.#boundLeave);
|
|
2002
2029
|
}
|
|
2003
2030
|
|
|
2031
|
+
#isTruncated() {
|
|
2032
|
+
const overflows = (el) => el.scrollWidth > el.clientWidth;
|
|
2033
|
+
if (overflows(this)) return true;
|
|
2034
|
+
return [...this.querySelectorAll(":scope > .start, :scope > .end")].some(
|
|
2035
|
+
overflows,
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2004
2039
|
#teardownTooltip() {
|
|
2005
2040
|
if (this.#boundEnter)
|
|
2006
2041
|
this.removeEventListener("pointerenter", this.#boundEnter);
|
|
2007
2042
|
if (this.#boundLeave)
|
|
2008
2043
|
this.removeEventListener("pointerleave", this.#boundLeave);
|
|
2044
|
+
this.#boundEnter = null;
|
|
2045
|
+
this.#boundLeave = null;
|
|
2009
2046
|
FigTooltip.hide(this);
|
|
2010
2047
|
}
|
|
2011
2048
|
}
|
|
@@ -18698,23 +18735,29 @@ figDefineElement("fig-skeleton", FigSkeleton);
|
|
|
18698
18735
|
|
|
18699
18736
|
// FigGroup
|
|
18700
18737
|
class FigGroup extends HTMLElement {
|
|
18701
|
-
static observedAttributes = ["name", "collapsible", "open"];
|
|
18738
|
+
static observedAttributes = ["name", "collapsible", "open", "compact"];
|
|
18702
18739
|
|
|
18703
18740
|
#header = null;
|
|
18704
18741
|
#chevron = null;
|
|
18742
|
+
#toggle = null;
|
|
18743
|
+
#compactHeader = null;
|
|
18744
|
+
#compactHeaderValue = null;
|
|
18705
18745
|
|
|
18706
18746
|
connectedCallback() {
|
|
18707
18747
|
this.#render();
|
|
18708
18748
|
}
|
|
18709
18749
|
|
|
18710
18750
|
disconnectedCallback() {
|
|
18711
|
-
|
|
18712
|
-
|
|
18713
|
-
|
|
18751
|
+
this.#removeToggleListeners();
|
|
18752
|
+
}
|
|
18753
|
+
|
|
18754
|
+
#removeToggleListeners() {
|
|
18755
|
+
this.#chevron?.removeEventListener("click", this.#handleToggle);
|
|
18756
|
+
this.#toggle?.removeEventListener("click", this.#handleToggle);
|
|
18757
|
+
this.#toggle?.removeEventListener("keydown", this.#handleToggleKeyDown);
|
|
18714
18758
|
if (this.#header) {
|
|
18715
18759
|
this.#header.removeEventListener("click", this.#handleToggle);
|
|
18716
|
-
this.#header.removeEventListener("keydown", this.#
|
|
18717
|
-
this.#header.querySelector("h3")?.removeEventListener("click", this.#handleToggle);
|
|
18760
|
+
this.#header.removeEventListener("keydown", this.#handleToggleKeyDown);
|
|
18718
18761
|
}
|
|
18719
18762
|
}
|
|
18720
18763
|
|
|
@@ -18722,7 +18765,7 @@ class FigGroup extends HTMLElement {
|
|
|
18722
18765
|
if (oldValue === newValue) return;
|
|
18723
18766
|
if (!this.isConnected) return;
|
|
18724
18767
|
if (name === "open") {
|
|
18725
|
-
this.#
|
|
18768
|
+
this.#syncExpanded();
|
|
18726
18769
|
return;
|
|
18727
18770
|
}
|
|
18728
18771
|
this.#render();
|
|
@@ -18740,7 +18783,7 @@ class FigGroup extends HTMLElement {
|
|
|
18740
18783
|
} else {
|
|
18741
18784
|
this.setAttribute("open", "false");
|
|
18742
18785
|
}
|
|
18743
|
-
this.#
|
|
18786
|
+
this.#syncExpanded();
|
|
18744
18787
|
if (was !== !!value) {
|
|
18745
18788
|
this.dispatchEvent(
|
|
18746
18789
|
new CustomEvent("openchange", {
|
|
@@ -18751,12 +18794,46 @@ class FigGroup extends HTMLElement {
|
|
|
18751
18794
|
}
|
|
18752
18795
|
}
|
|
18753
18796
|
|
|
18797
|
+
#syncExpanded() {
|
|
18798
|
+
if (this.hasAttribute("collapsible")) {
|
|
18799
|
+
this.#toggle?.setAttribute("aria-expanded", String(this.open));
|
|
18800
|
+
} else {
|
|
18801
|
+
this.#toggle?.removeAttribute("aria-expanded");
|
|
18802
|
+
}
|
|
18803
|
+
}
|
|
18804
|
+
|
|
18805
|
+
#restoreHeaderCompact() {
|
|
18806
|
+
if (!this.#compactHeader) return;
|
|
18807
|
+
if (this.#compactHeaderValue === null) {
|
|
18808
|
+
this.#compactHeader.removeAttribute("compact");
|
|
18809
|
+
} else {
|
|
18810
|
+
this.#compactHeader.setAttribute("compact", this.#compactHeaderValue);
|
|
18811
|
+
}
|
|
18812
|
+
this.#compactHeader = null;
|
|
18813
|
+
this.#compactHeaderValue = null;
|
|
18814
|
+
}
|
|
18815
|
+
|
|
18816
|
+
#syncHeaderCompact() {
|
|
18817
|
+
const compact =
|
|
18818
|
+
this.hasAttribute("compact") && this.getAttribute("compact") !== "false";
|
|
18819
|
+
if (!compact) {
|
|
18820
|
+
this.#restoreHeaderCompact();
|
|
18821
|
+
return;
|
|
18822
|
+
}
|
|
18823
|
+
if (this.#compactHeader !== this.#header) {
|
|
18824
|
+
this.#restoreHeaderCompact();
|
|
18825
|
+
this.#compactHeader = this.#header;
|
|
18826
|
+
this.#compactHeaderValue = this.#header?.getAttribute("compact") ?? null;
|
|
18827
|
+
}
|
|
18828
|
+
this.#header?.setAttribute("compact", "");
|
|
18829
|
+
}
|
|
18830
|
+
|
|
18754
18831
|
#handleToggle = (e) => {
|
|
18755
18832
|
e.stopPropagation();
|
|
18756
18833
|
this.open = !this.open;
|
|
18757
18834
|
};
|
|
18758
18835
|
|
|
18759
|
-
#
|
|
18836
|
+
#handleToggleKeyDown = (e) => {
|
|
18760
18837
|
if (e.key !== "Enter" && e.key !== " ") return;
|
|
18761
18838
|
e.preventDefault();
|
|
18762
18839
|
e.stopPropagation();
|
|
@@ -18764,6 +18841,7 @@ class FigGroup extends HTMLElement {
|
|
|
18764
18841
|
};
|
|
18765
18842
|
|
|
18766
18843
|
#render() {
|
|
18844
|
+
this.#removeToggleListeners();
|
|
18767
18845
|
const isCollapsible = this.hasAttribute("collapsible");
|
|
18768
18846
|
const nameAttr = this.getAttribute("name");
|
|
18769
18847
|
const label = nameAttr || (isCollapsible ? "Group" : null);
|
|
@@ -18775,9 +18853,11 @@ class FigGroup extends HTMLElement {
|
|
|
18775
18853
|
|
|
18776
18854
|
if (!label && !isCollapsible && !userHeader) {
|
|
18777
18855
|
if (this.#header && this.#header.dataset.generated) {
|
|
18856
|
+
this.#restoreHeaderCompact();
|
|
18778
18857
|
this.#header.remove();
|
|
18779
18858
|
this.#header = null;
|
|
18780
18859
|
this.#chevron = null;
|
|
18860
|
+
this.#toggle = null;
|
|
18781
18861
|
}
|
|
18782
18862
|
return;
|
|
18783
18863
|
}
|
|
@@ -18793,6 +18873,7 @@ class FigGroup extends HTMLElement {
|
|
|
18793
18873
|
this.#header.dataset.generated = "true";
|
|
18794
18874
|
this.prepend(this.#header);
|
|
18795
18875
|
}
|
|
18876
|
+
this.#syncHeaderCompact();
|
|
18796
18877
|
|
|
18797
18878
|
// Ensure h3 exists inside header
|
|
18798
18879
|
let h3 = this.#header.querySelector("h3");
|
|
@@ -18800,6 +18881,7 @@ class FigGroup extends HTMLElement {
|
|
|
18800
18881
|
h3 = document.createElement("h3");
|
|
18801
18882
|
this.#header.prepend(h3);
|
|
18802
18883
|
}
|
|
18884
|
+
this.#toggle = h3;
|
|
18803
18885
|
if (!h3.id) h3.id = figUniqueId();
|
|
18804
18886
|
if (this.#header.dataset.generated) {
|
|
18805
18887
|
h3.textContent = label;
|
|
@@ -18819,26 +18901,27 @@ class FigGroup extends HTMLElement {
|
|
|
18819
18901
|
}
|
|
18820
18902
|
this.#header.insertBefore(chevron, h3);
|
|
18821
18903
|
this.#chevron = chevron;
|
|
18822
|
-
|
|
18823
|
-
this.#header.
|
|
18824
|
-
this.#header.
|
|
18825
|
-
|
|
18826
|
-
|
|
18827
|
-
|
|
18828
|
-
|
|
18829
|
-
|
|
18904
|
+
this.#header.removeAttribute("role");
|
|
18905
|
+
this.#header.removeAttribute("tabindex");
|
|
18906
|
+
this.#header.removeAttribute("aria-expanded");
|
|
18907
|
+
h3.setAttribute("role", "button");
|
|
18908
|
+
h3.setAttribute("tabindex", "0");
|
|
18909
|
+
h3.setAttribute("aria-expanded", String(this.open));
|
|
18910
|
+
h3.addEventListener("click", this.#handleToggle);
|
|
18911
|
+
h3.addEventListener("keydown", this.#handleToggleKeyDown);
|
|
18912
|
+
chevron.addEventListener("click", this.#handleToggle);
|
|
18830
18913
|
|
|
18831
18914
|
if (!this.hasAttribute("open")) {
|
|
18832
18915
|
this.setAttribute("open", "false");
|
|
18833
|
-
|
|
18916
|
+
h3.setAttribute("aria-expanded", "false");
|
|
18834
18917
|
}
|
|
18835
18918
|
} else {
|
|
18836
|
-
h3.
|
|
18837
|
-
|
|
18919
|
+
h3.removeAttribute("role");
|
|
18920
|
+
h3.removeAttribute("tabindex");
|
|
18921
|
+
h3.removeAttribute("aria-expanded");
|
|
18838
18922
|
this.#header.removeAttribute("role");
|
|
18839
18923
|
this.#header.removeAttribute("tabindex");
|
|
18840
18924
|
this.#header.removeAttribute("aria-expanded");
|
|
18841
|
-
this.#header.removeEventListener("keydown", this.#handleHeaderKeyDown);
|
|
18842
18925
|
if (this.#chevron) {
|
|
18843
18926
|
this.#chevron.remove();
|
|
18844
18927
|
this.#chevron = null;
|
package/package.json
CHANGED