katalyst-tables 3.5.5 → 3.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/builds/katalyst/tables.esm.js +197 -24
- data/app/assets/builds/katalyst/tables.js +197 -24
- data/app/assets/builds/katalyst/tables.min.js +1 -1
- data/app/assets/builds/katalyst/tables.min.js.map +1 -1
- data/app/assets/stylesheets/katalyst/tables/_query.scss +37 -3
- data/app/components/katalyst/tables/query/input_component.html.erb +6 -1
- data/app/components/katalyst/tables/query/input_component.rb +5 -1
- data/app/components/katalyst/tables/query/modal_component.html.erb +2 -2
- data/app/components/katalyst/tables/query/modal_component.rb +7 -2
- data/app/components/katalyst/tables/query/suggestion_component.rb +21 -1
- data/app/components/katalyst/tables/query_component.rb +1 -0
- data/app/javascript/tables/query_controller.js +91 -11
- data/app/javascript/tables/query_input_controller.js +105 -12
- data/config/locales/tables.en.yml +2 -2
- metadata +2 -2
@@ -725,6 +725,7 @@ class QueryController extends Controller {
|
|
725
725
|
|
726
726
|
closeModal() {
|
727
727
|
delete this.modalTarget.dataset.open;
|
728
|
+
this.query.setAttribute("aria-expanded", false);
|
728
729
|
|
729
730
|
if (document.activeElement === this.query) document.activeElement.blur();
|
730
731
|
|
@@ -733,6 +734,7 @@ class QueryController extends Controller {
|
|
733
734
|
|
734
735
|
openModal() {
|
735
736
|
this.modalTarget.dataset.open = true;
|
737
|
+
this.query.setAttribute("aria-expanded", true);
|
736
738
|
|
737
739
|
document.addEventListener("selectionchange", this.selection);
|
738
740
|
}
|
@@ -761,25 +763,26 @@ class QueryController extends Controller {
|
|
761
763
|
delete this.pending;
|
762
764
|
}
|
763
765
|
|
764
|
-
//
|
766
|
+
// add/remove current cursor position
|
767
|
+
if (hasFocus && this.query.value !== "") {
|
768
|
+
this.position.value = position;
|
769
|
+
this.position.disabled = false;
|
770
|
+
} else {
|
771
|
+
this.position.value = "";
|
772
|
+
this.position.disabled = true;
|
773
|
+
}
|
774
|
+
|
775
|
+
// prevent an unnecessary `?q=&p=0` parameter from appearing in the URL
|
765
776
|
if (this.query.value === "") {
|
766
777
|
this.query.disabled = true;
|
767
778
|
|
768
779
|
// restore input and focus after form submission
|
769
780
|
setTimeout(() => {
|
770
781
|
this.query.disabled = false;
|
782
|
+
this.position.disabled = false;
|
771
783
|
if (hasFocus) this.query.focus();
|
772
784
|
}, 0);
|
773
785
|
}
|
774
|
-
|
775
|
-
// add/remove current cursor position
|
776
|
-
if (hasFocus && position) {
|
777
|
-
this.position.value = position;
|
778
|
-
this.position.disabled = false;
|
779
|
-
} else {
|
780
|
-
this.position.value = "";
|
781
|
-
this.position.disabled = true;
|
782
|
-
}
|
783
786
|
}
|
784
787
|
|
785
788
|
update = () => {
|
@@ -801,8 +804,85 @@ class QueryController extends Controller {
|
|
801
804
|
}
|
802
805
|
}
|
803
806
|
|
807
|
+
moveToPreviousSuggestion() {
|
808
|
+
const prev = this.previousSuggestion || this.lastSuggestion;
|
809
|
+
|
810
|
+
if (prev) this.makeSuggestionActive(prev);
|
811
|
+
}
|
812
|
+
|
813
|
+
moveToNextSuggestion() {
|
814
|
+
const next = this.nextSuggestion || this.firstSuggestion;
|
815
|
+
|
816
|
+
if (next) this.makeSuggestionActive(next);
|
817
|
+
}
|
818
|
+
|
819
|
+
selectFirstSuggestion(e) {
|
820
|
+
// This is caused by pressing the tab key. We don't want to move focus.
|
821
|
+
// Ideally we don't want to always prevent the user from tabbing. We will address this later
|
822
|
+
e.preventDefault();
|
823
|
+
|
824
|
+
this.firstSuggestion?.dispatchEvent(new CustomEvent("query:select"));
|
825
|
+
}
|
826
|
+
|
827
|
+
selectActiveSuggestion() {
|
828
|
+
if (!this.activeSuggestion) {
|
829
|
+
this.closeModal();
|
830
|
+
return;
|
831
|
+
}
|
832
|
+
|
833
|
+
this.activeSuggestion.dispatchEvent(new CustomEvent("query:select"));
|
834
|
+
}
|
835
|
+
|
836
|
+
selectSuggestion(e) {
|
837
|
+
this.query.dispatchEvent(
|
838
|
+
new CustomEvent("replaceToken", {
|
839
|
+
detail: { token: e.params.value, position: this.query.selectionStart },
|
840
|
+
}),
|
841
|
+
);
|
842
|
+
|
843
|
+
this.clearActiveSuggestion();
|
844
|
+
}
|
845
|
+
|
846
|
+
makeSuggestionActive(node) {
|
847
|
+
if (this.activeSuggestion) {
|
848
|
+
this.activeSuggestion.setAttribute("aria-selected", "false");
|
849
|
+
}
|
850
|
+
|
851
|
+
this.query.setAttribute("aria-activedescendant", node.id);
|
852
|
+
node.setAttribute("aria-selected", "true");
|
853
|
+
}
|
854
|
+
|
855
|
+
clearActiveSuggestion() {
|
856
|
+
if (this.activeSuggestion) {
|
857
|
+
this.activeSuggestion.setAttribute("aria-selected", "false");
|
858
|
+
this.query.removeAttribute("aria-activedescendant");
|
859
|
+
}
|
860
|
+
}
|
861
|
+
|
862
|
+
get activeSuggestion() {
|
863
|
+
return this.modalTarget.querySelector(
|
864
|
+
`#${this.query.getAttribute("aria-activedescendant")}`,
|
865
|
+
);
|
866
|
+
}
|
867
|
+
|
868
|
+
get previousSuggestion() {
|
869
|
+
return this.activeSuggestion?.previousElementSibling;
|
870
|
+
}
|
871
|
+
|
872
|
+
get nextSuggestion() {
|
873
|
+
return this.activeSuggestion?.nextElementSibling;
|
874
|
+
}
|
875
|
+
|
876
|
+
get firstSuggestion() {
|
877
|
+
return this.modalTarget.querySelector("#suggestions li:first-of-type");
|
878
|
+
}
|
879
|
+
|
880
|
+
get lastSuggestion() {
|
881
|
+
return this.modalTarget.querySelector("#suggestions li:last-of-type");
|
882
|
+
}
|
883
|
+
|
804
884
|
get query() {
|
805
|
-
return this.element.querySelector("[role=
|
885
|
+
return this.element.querySelector("[role=combobox]");
|
806
886
|
}
|
807
887
|
|
808
888
|
get position() {
|
@@ -838,6 +918,49 @@ class QueryInputController extends Controller {
|
|
838
918
|
this.highlightTarget.appendChild(token.render());
|
839
919
|
});
|
840
920
|
}
|
921
|
+
|
922
|
+
replaceToken(e) {
|
923
|
+
let tokenToAdd = e.detail.token.toString();
|
924
|
+
|
925
|
+
// wrap in quotes if it contains a spaces or special characters
|
926
|
+
if (/\s/.exec(tokenToAdd)) {
|
927
|
+
tokenToAdd = `"${tokenToAdd}"`;
|
928
|
+
}
|
929
|
+
|
930
|
+
const indexPosition = e.detail.position;
|
931
|
+
let caretPosition = indexPosition + tokenToAdd.length;
|
932
|
+
let sliceStart = indexPosition;
|
933
|
+
let sliceEnd = indexPosition;
|
934
|
+
|
935
|
+
// detect if position has a token already, if so, replace it
|
936
|
+
const existingToken = new Parser()
|
937
|
+
.parse(this.queryValue)
|
938
|
+
.tokenAtPosition(indexPosition);
|
939
|
+
if (existingToken) {
|
940
|
+
// We don't want to include the trailing space as we are replacing an existing value
|
941
|
+
tokenToAdd = tokenToAdd.trim();
|
942
|
+
|
943
|
+
// Slice up to the beginning of the tokens value (not the initial caret position)
|
944
|
+
sliceStart = existingToken.startOfValue();
|
945
|
+
|
946
|
+
// Slice after the end of the tokens value
|
947
|
+
sliceEnd = existingToken.endOfValue();
|
948
|
+
|
949
|
+
// The end position of the newly added token
|
950
|
+
caretPosition = sliceStart + tokenToAdd.length;
|
951
|
+
}
|
952
|
+
|
953
|
+
// Replace any text within sliceStart and sliceEnd with tokenToAdd
|
954
|
+
this.inputTarget.value =
|
955
|
+
this.queryValue.slice(0, sliceStart) +
|
956
|
+
tokenToAdd +
|
957
|
+
this.queryValue.slice(sliceEnd);
|
958
|
+
|
959
|
+
// Re focus the input at the end of the newly added token
|
960
|
+
this.update();
|
961
|
+
this.inputTarget.focus();
|
962
|
+
this.inputTarget.setSelectionRange(caretPosition, caretPosition);
|
963
|
+
}
|
841
964
|
}
|
842
965
|
|
843
966
|
class Parser {
|
@@ -871,13 +994,13 @@ class Parser {
|
|
871
994
|
skipWhitespace(query) {
|
872
995
|
if (!query.scan(/\s+/)) return;
|
873
996
|
|
874
|
-
return new Token(query.matched());
|
997
|
+
return new Token(query.matched(), query.position);
|
875
998
|
}
|
876
999
|
|
877
1000
|
takeUntagged(query) {
|
878
1001
|
if (!query.scan(/\S+/)) return;
|
879
1002
|
|
880
|
-
return new Untagged(query.matched());
|
1003
|
+
return new Untagged(query.matched(), query.position);
|
881
1004
|
}
|
882
1005
|
|
883
1006
|
takeTagged(query) {
|
@@ -889,13 +1012,13 @@ class Parser {
|
|
889
1012
|
const value =
|
890
1013
|
this.takeArrayValue(query) || this.takeSingleValue(query) || new Token();
|
891
1014
|
|
892
|
-
return new Tagged(key, separator, value);
|
1015
|
+
return new Tagged(key, separator, value, query.position);
|
893
1016
|
}
|
894
1017
|
|
895
1018
|
takeArrayValue(query) {
|
896
1019
|
if (!query.scan(/\[\s*/)) return;
|
897
1020
|
|
898
|
-
const start = new Token(query.matched());
|
1021
|
+
const start = new Token(query.matched(), query.position);
|
899
1022
|
const values = (this.values = []);
|
900
1023
|
|
901
1024
|
while (!query.isEos()) {
|
@@ -904,17 +1027,17 @@ class Parser {
|
|
904
1027
|
}
|
905
1028
|
|
906
1029
|
query.scan(/\s*]/);
|
907
|
-
const end = new Token(query.matched());
|
1030
|
+
const end = new Token(query.matched(), query.position);
|
908
1031
|
|
909
1032
|
this.values = null;
|
910
1033
|
|
911
|
-
return new
|
1034
|
+
return new ArrayToken(start, values, end);
|
912
1035
|
}
|
913
1036
|
|
914
1037
|
takeDelimiter(query) {
|
915
1038
|
if (!query.scan(/\s*,\s*/)) return;
|
916
1039
|
|
917
|
-
return new Token(query.matched());
|
1040
|
+
return new Token(query.matched(), query.position);
|
918
1041
|
}
|
919
1042
|
|
920
1043
|
takeSingleValue(query) {
|
@@ -924,24 +1047,49 @@ class Parser {
|
|
924
1047
|
takeQuotedValue(query) {
|
925
1048
|
if (!query.scan(/"([^"]*)"/)) return;
|
926
1049
|
|
927
|
-
return new Value(query.matched());
|
1050
|
+
return new Value(query.matched(), query.position);
|
928
1051
|
}
|
929
1052
|
|
930
1053
|
takeUnquotedValue(query) {
|
931
1054
|
if (!query.scan(/[^ \],]*/)) return;
|
932
1055
|
|
933
|
-
return new Value(query.matched());
|
1056
|
+
return new Value(query.matched(), query.position);
|
1057
|
+
}
|
1058
|
+
|
1059
|
+
tokenAtPosition(position) {
|
1060
|
+
return this.tokens
|
1061
|
+
.filter((t) => t instanceof Tagged || t instanceof Untagged)
|
1062
|
+
.find((t) => t.range.includes(position));
|
934
1063
|
}
|
935
1064
|
}
|
936
1065
|
|
937
1066
|
class Token {
|
938
|
-
constructor(value = "") {
|
1067
|
+
constructor(value = "", position) {
|
939
1068
|
this.value = value;
|
1069
|
+
this.length = this.value.length;
|
1070
|
+
this.start = position - this.length;
|
1071
|
+
this.end = this.start + this.length;
|
1072
|
+
this.range = this.arrayRange(this.start, this.end);
|
940
1073
|
}
|
941
1074
|
|
942
1075
|
render() {
|
943
1076
|
return document.createTextNode(this.value);
|
944
1077
|
}
|
1078
|
+
|
1079
|
+
arrayRange(start, stop) {
|
1080
|
+
return Array.from(
|
1081
|
+
{ length: stop - start + 1 },
|
1082
|
+
(value, index) => start + index,
|
1083
|
+
);
|
1084
|
+
}
|
1085
|
+
|
1086
|
+
startOfValue() {
|
1087
|
+
return this.start;
|
1088
|
+
}
|
1089
|
+
|
1090
|
+
endOfValue() {
|
1091
|
+
return this.end;
|
1092
|
+
}
|
945
1093
|
}
|
946
1094
|
|
947
1095
|
class Value extends Token {
|
@@ -955,12 +1103,16 @@ class Value extends Token {
|
|
955
1103
|
}
|
956
1104
|
|
957
1105
|
class Tagged extends Token {
|
958
|
-
constructor(key, separator, value) {
|
1106
|
+
constructor(key, separator, value, position) {
|
959
1107
|
super();
|
960
1108
|
|
961
1109
|
this.key = key;
|
962
1110
|
this.separator = separator;
|
963
1111
|
this.value = value;
|
1112
|
+
this.length = key.length + separator.length + value.value.length;
|
1113
|
+
this.start = position - this.length;
|
1114
|
+
this.end = this.start + this.length;
|
1115
|
+
this.range = this.arrayRange(this.start, this.end);
|
964
1116
|
}
|
965
1117
|
|
966
1118
|
render() {
|
@@ -977,6 +1129,14 @@ class Tagged extends Token {
|
|
977
1129
|
|
978
1130
|
return span;
|
979
1131
|
}
|
1132
|
+
|
1133
|
+
startOfValue() {
|
1134
|
+
return this.value.startOfValue();
|
1135
|
+
}
|
1136
|
+
|
1137
|
+
endOfValue() {
|
1138
|
+
return this.value.endOfValue();
|
1139
|
+
}
|
980
1140
|
}
|
981
1141
|
|
982
1142
|
class Untagged extends Token {
|
@@ -988,13 +1148,18 @@ class Untagged extends Token {
|
|
988
1148
|
}
|
989
1149
|
}
|
990
1150
|
|
991
|
-
|
1151
|
+
class ArrayToken extends Token {
|
992
1152
|
constructor(start, values, end) {
|
993
1153
|
super();
|
994
1154
|
|
995
1155
|
this.start = start;
|
996
1156
|
this.values = values;
|
997
1157
|
this.end = end;
|
1158
|
+
this.range = this.arrayRange(start.start, end.range[end.length]);
|
1159
|
+
this.length =
|
1160
|
+
start.length +
|
1161
|
+
values.reduce((length, value) => length + value.length, 0) +
|
1162
|
+
end.length;
|
998
1163
|
}
|
999
1164
|
|
1000
1165
|
render() {
|
@@ -1012,7 +1177,15 @@ let Array$1 = class Array extends Token {
|
|
1012
1177
|
|
1013
1178
|
return array;
|
1014
1179
|
}
|
1015
|
-
|
1180
|
+
|
1181
|
+
startOfValue() {
|
1182
|
+
return this.start.start;
|
1183
|
+
}
|
1184
|
+
|
1185
|
+
endOfValue() {
|
1186
|
+
return this.end.end;
|
1187
|
+
}
|
1188
|
+
}
|
1016
1189
|
|
1017
1190
|
class StringScanner {
|
1018
1191
|
constructor(input) {
|
@@ -1,2 +1,2 @@
|
|
1
|
-
import{Controller as e}from"@hotwired/stimulus";class t{constructor(e,t,s){this.cursorOffset=t.offsetY,this.initialPosition=t.target.offsetTop-e.offsetTop,this.targetId=s}updateCursor(e,t,s,i){this.listOffset=e.getBoundingClientRect().top;let a=s.clientY-this.listOffset-this.cursorOffset;this.#e(e,t,a,i)}updateScroll(e,t,s){const i=this.listOffset;this.listOffset=e.getBoundingClientRect().top;const a=i-this.listOffset,r=this.position+a;this.#e(e,t,r,s)}#e(e,t,s,i){s=Math.max(s,0),s=Math.min(s,e.offsetHeight-t.offsetHeight),this.position=s;i(s-this.initialPosition)}}class s extends e{static outlets=["tables--selection--form"];static values={params:Object,checked:Boolean};tablesSelectionFormOutletConnected(e){e.visible(this.id,!0),this.checkedValue=e.isSelected(this.id)}disconnect(){this.hasTablesSelectionFormOutlet&&this.tablesSelectionFormOutlet.visible(this.id,!1)}change(e){e.preventDefault(),this.checkedValue=this.tablesSelectionFormOutlet.toggle(this.id)}get id(){return this.paramsValue.id}paramsValueChanged(e,t){this.hasTablesSelectionFormOutlet&&(t.id!==e.id&&this.tablesSelectionFormOutlet.visible(t.id,!1),this.tablesSelectionFormOutlet.visible(e.id,!0),this.checkedValue=this.tablesSelectionFormOutlet.isSelected(e.id),this.update())}checkedValueChanged(){this.hasTablesSelectionFormOutlet&&(this.checkedValue=this.tablesSelectionFormOutlet.isSelected(this.id),this.update())}async update(){return this.updating||=Promise.resolve().then((()=>{this.#t(),delete this.updating})),this.updating}#t(){this.element.querySelector("input").checked=this.checkedValue,this.dispatch("select",{detail:{id:this.id,selected:this.checkedValue}})}}class i{constructor(){this.tokens=[],this.values=null}parse(e){const t=new h(e);for(;!t.isEos();){this.push(this.skipWhitespace(t));const e=this.takeTagged(t)||this.takeUntagged(t);if(!this.push(e))break}return this}push(e){return e&&(this.values?this.values.push(e):this.tokens.push(e)),!!e}skipWhitespace(e){if(e.scan(/\s+/))return new a(e.matched())}takeUntagged(e){if(e.scan(/\S+/))return new l(e.matched())}takeTagged(e){if(!e.scan(/(\w+(?:\.\w+)?)(:\s*)/))return;const t=e.valueAt(1),s=e.valueAt(2),i=this.takeArrayValue(e)||this.takeSingleValue(e)||new a;return new n(t,s,i)}takeArrayValue(e){if(!e.scan(/\[\s*/))return;const t=new a(e.matched()),s=this.values=[];for(;!e.isEos()&&this.push(this.takeSingleValue(e))&&this.push(this.takeDelimiter(e)););e.scan(/\s*]/);const i=new a(e.matched());return this.values=null,new o(t,s,i)}takeDelimiter(e){if(e.scan(/\s*,\s*/))return new a(e.matched())}takeSingleValue(e){return this.takeQuotedValue(e)||this.takeUnquotedValue(e)}takeQuotedValue(e){if(e.scan(/"([^"]*)"/))return new r(e.matched())}takeUnquotedValue(e){if(e.scan(/[^ \],]*/))return new r(e.matched())}}class a{constructor(e=""){this.value=e}render(){return document.createTextNode(this.value)}}class r extends a{render(){const e=document.createElement("span");return e.className="value",e.innerText=this.value,e}}class n extends a{constructor(e,t,s){super(),this.key=e,this.separator=t,this.value=s}render(){const e=document.createElement("span");e.className="tag";const t=document.createElement("span");return t.className="key",t.innerText=this.key,e.appendChild(t),e.appendChild(document.createTextNode(this.separator)),e.appendChild(this.value.render()),e}}class l extends a{render(){const e=document.createElement("span");return e.className="untagged",e.innerText=this.value,e}}let o=class extends a{constructor(e,t,s){super(),this.start=e,this.values=t,this.end=s}render(){const e=document.createElement("span");return e.className="array-values",e.appendChild(this.start.render()),this.values.forEach((t=>{const s=document.createElement("span");s.appendChild(t.render()),e.appendChild(s)})),e.appendChild(this.end.render()),e}};class h{constructor(e){this.input=e,this.position=0,this.last=null}isEos(){return this.position>=this.input.length}scan(e){const t=e.exec(this.input.substring(this.position));return 0===t?.index?(this.last=t,this.position+=t[0].length,!0):(this.last={},!1)}matched(){return this.last&&this.last[0]}valueAt(e){return this.last&&this.last[e]}}const u=[{identifier:"tables--orderable--item",controllerConstructor:class extends e{static values={params:Object};connect(){var e;this.index=(e=this.row,Array.from(e.parentElement.children).indexOf(e))}paramsValueChanged(e){this.id=e.id_value}dragUpdate(e){this.dragOffset=e,this.row.style.position="relative",this.row.style.top=e+"px",this.row.style.zIndex="1",this.row.toggleAttribute("dragging",!0)}updateVisually(e){this.row.style.position="relative",this.row.style.top=this.row.offsetHeight*(e-this.dragIndex)+"px"}updateIndex(e){this.index=e}params(e){const{id_name:t,id_value:s,index_name:i}=this.paramsValue;return[{name:`${e}[${s}][${t}]`,value:this.id},{name:`${e}[${s}][${i}]`,value:this.index}]}reset(){delete this.dragOffset,this.row.removeAttribute("style"),this.row.removeAttribute("dragging")}get hasChanges(){return this.paramsValue.index_value!==this.index}get dragIndex(){return this.dragOffset&&0!==this.dragOffset?this.index+Math.round(this.dragOffset/this.row.offsetHeight):this.index}get comparisonIndex(){return this.dragOffset?this.dragIndex+(this.dragOffset>0?.5:-.5):this.index}get row(){return this.element.parentElement}}},{identifier:"tables--orderable--list",controllerConstructor:class extends e{static outlets=["tables--orderable--item","tables--orderable--form"];startDragging(e){this.dragState=e,document.addEventListener("mousemove",this.mousemove),document.addEventListener("mouseup",this.mouseup),window.addEventListener("scroll",this.scroll,!0),this.element.style.position="relative"}stopDragging(){const e=this.dragState;return delete this.dragState,document.removeEventListener("mousemove",this.mousemove),document.removeEventListener("mouseup",this.mouseup),window.removeEventListener("scroll",this.scroll,!0),this.element.removeAttribute("style"),this.tablesOrderableItemOutlets.forEach((e=>e.reset())),e}drop(){const e=this.dragItem;if(!e)return;const t=e.dragIndex,s=this.tablesOrderableItemOutlets[t];s&&(t<e.index?s.row.insertAdjacentElement("beforebegin",e.row):t>e.index&&s.row.insertAdjacentElement("afterend",e.row),this.tablesOrderableItemOutlets.forEach(((e,t)=>e.updateIndex(t))),this.commitChanges())}commitChanges(){this.tablesOrderableFormOutlet.clear(),this.tablesOrderableItemOutlets.forEach((e=>{e.hasChanges&&this.tablesOrderableFormOutlet.add(e)})),this.tablesOrderableFormOutlet.submit()}mousedown(e){if(this.isDragging)return;const s=this.#s(e.target);s&&(e.preventDefault(),this.startDragging(new t(this.element,e,s.id)),this.dragState.updateCursor(this.element,s.row,e,this.animate))}mousemove=e=>{this.isDragging&&(e.preventDefault(),this.ticking||(this.ticking=!0,window.requestAnimationFrame((()=>{this.ticking=!1,this.dragState?.updateCursor(this.element,this.dragItem.row,e,this.animate)}))))};scroll=e=>{this.isDragging&&!this.ticking&&(this.ticking=!0,window.requestAnimationFrame((()=>{this.ticking=!1,this.dragState?.updateScroll(this.element,this.dragItem.row,this.animate)})))};mouseup=e=>{this.isDragging&&(this.drop(),this.stopDragging(),this.tablesOrderableFormOutlets.forEach((e=>delete e.dragState)))};tablesOrderableFormOutletConnected(e,t){e.dragState&&this.startDragging(e.dragState)}tablesOrderableFormOutletDisconnected(e,t){this.isDragging&&(e.dragState=this.stopDragging())}beforeMorphAttribute(e){switch(e.detail.attributeName){case"dragging":e.preventDefault();break;case"style":"TBODY"!==e.target.tagName&&"TR"!==e.target.tagName||e.preventDefault()}}animate=e=>{const t=this.dragItem;t.dragUpdate(e),this.#i.forEach(((e,s)=>{e!==t&&e.updateVisually(s)}))};get isDragging(){return!!this.dragState}get dragItem(){return this.isDragging?this.tablesOrderableItemOutlets.find((e=>e.id===this.dragState.targetId)):null}get#i(){return this.tablesOrderableItemOutlets.toSorted(((e,t)=>e.comparisonIndex-t.comparisonIndex))}#s(e){return this.tablesOrderableItemOutlets.find((t=>t.element===e))}}},{identifier:"tables--orderable--form",controllerConstructor:class extends e{static values={scope:String};add(e){e.params(this.scopeValue).forEach((({name:e,value:t})=>{this.element.insertAdjacentHTML("beforeend",`<input type="hidden" name="${e}" value="${t}" data-generated>`)}))}submit(){0!==this.inputs.length&&this.element.requestSubmit()}clear(){this.inputs.forEach((e=>e.remove()))}get inputs(){return this.element.querySelectorAll("input[data-generated]")}}},{identifier:"tables--selection--form",controllerConstructor:class extends e{static values={count:Number,primaryKey:{type:String,default:"id"}};static targets=["count","singular","plural"];connect(){this.countValue=this.inputs.length}toggle(e){const t=this.input(e);return t?t.remove():this.element.insertAdjacentHTML("beforeend",`<input type="hidden" name="${this.primaryKeyValue}[]" value="${e}">`),this.countValue=this.visibleInputs.length,!t}visible(e,t){const s=this.input(e);return s&&(s.disabled=!t),this.countValue=this.visibleInputs.length,!s}isSelected(e){return!!this.input(e)}get inputs(){return this.element.querySelectorAll(`input[name="${this.primaryKeyValue}[]"]`)}get visibleInputs(){return Array.from(this.inputs).filter((e=>!e.disabled))}input(e){return this.element.querySelector(`input[name="${this.primaryKeyValue}[]"][value="${e}"]`)}countValueChanged(e){this.element.toggleAttribute("hidden",0===e),this.countTarget.textContent=e,this.singularTarget.toggleAttribute("hidden",1!==e),this.pluralTarget.toggleAttribute("hidden",1===e)}}},{identifier:"tables--selection--item",controllerConstructor:s},{identifier:"tables--selection--table",controllerConstructor:class extends e{static targets=["header","item"];static outlets=["tables--selection--form"];itemTargetConnected(e){this.update()}itemTargetDisconnected(e){this.update()}toggleHeader(e){this.items.forEach((t=>{t.checkedValue!==e.target.checked&&(t.checkedValue=this.tablesSelectionFormOutlet.toggle(t.id))}))}async update(){return this.updating||=Promise.resolve().then((()=>{this.#t(),delete this.updating})),this.updating}#t(){let e=0,t=0;this.items.forEach((s=>{e++,s.checkedValue&&t++})),this.headerInput.checked=e>0&&t===e,this.headerInput.indeterminate=t>0&&t!==e}get headerInput(){return this.headerTarget.querySelector("input")}get items(){return this.itemTargets.map((e=>this.#a(e))).filter((e=>e))}#a(e){return this.application.getControllerForElementAndIdentifier(e,"tables--selection--item")}}},{identifier:"tables--query",controllerConstructor:class extends e{static targets=["modal"];disconnect(){delete this.pending,document.removeEventListener("selectionchange",this.selection)}focus(){document.activeElement!==this.query&&(this.query.addEventListener("focusin",(e=>{e.target.setSelectionRange(-1,-1)}),{once:!0}),this.query.focus())}closeModal(){delete this.modalTarget.dataset.open,document.activeElement===this.query&&document.activeElement.blur(),document.removeEventListener("selectionchange",this.selection)}openModal(){this.modalTarget.dataset.open=!0,document.addEventListener("selectionchange",this.selection)}clear(){""===this.query.value?this.closeModal():(this.query.value="",this.query.dispatchEvent(new Event("input")),this.query.dispatchEvent(new Event("change")),this.update())}submit(){const e=this.isFocused,t=e&&this.query.selectionStart;this.pending&&(clearTimeout(this.pending),delete this.pending),""===this.query.value&&(this.query.disabled=!0,setTimeout((()=>{this.query.disabled=!1,e&&this.query.focus()}),0)),e&&t?(this.position.value=t,this.position.disabled=!1):(this.position.value="",this.position.disabled=!0)}update=()=>{this.pending&&clearTimeout(this.pending),this.pending=setTimeout((()=>{this.element.requestSubmit()}),300)};selection=()=>{this.isFocused&&this.query.value.length>0&&this.update()};beforeMorphAttribute(e){if("data-open"===e.detail.attributeName)e.preventDefault()}get query(){return this.element.querySelector("[role=searchbox]")}get position(){return this.element.querySelector("input[name=p]")}get isFocused(){return this.query===document.activeElement}}},{identifier:"tables--query-input",controllerConstructor:class extends e{static targets=["input","highlight"];static values={query:String};connect(){this.queryValue=this.inputTarget.value,this.element.dataset.connected=""}disconnect(){delete this.element.dataset.connected}update(){this.queryValue=this.inputTarget.value}queryValueChanged(e){this.highlightTarget.innerHTML="",(new i).parse(e).tokens.forEach((e=>{this.highlightTarget.appendChild(e.render())}))}}}];export{u as default};
|
1
|
+
import{Controller as e}from"@hotwired/stimulus";class t{constructor(e,t,s){this.cursorOffset=t.offsetY,this.initialPosition=t.target.offsetTop-e.offsetTop,this.targetId=s}updateCursor(e,t,s,i){this.listOffset=e.getBoundingClientRect().top;let n=s.clientY-this.listOffset-this.cursorOffset;this.#e(e,t,n,i)}updateScroll(e,t,s){const i=this.listOffset;this.listOffset=e.getBoundingClientRect().top;const n=i-this.listOffset,a=this.position+n;this.#e(e,t,a,s)}#e(e,t,s,i){s=Math.max(s,0),s=Math.min(s,e.offsetHeight-t.offsetHeight),this.position=s;i(s-this.initialPosition)}}class s extends e{static outlets=["tables--selection--form"];static values={params:Object,checked:Boolean};tablesSelectionFormOutletConnected(e){e.visible(this.id,!0),this.checkedValue=e.isSelected(this.id)}disconnect(){this.hasTablesSelectionFormOutlet&&this.tablesSelectionFormOutlet.visible(this.id,!1)}change(e){e.preventDefault(),this.checkedValue=this.tablesSelectionFormOutlet.toggle(this.id)}get id(){return this.paramsValue.id}paramsValueChanged(e,t){this.hasTablesSelectionFormOutlet&&(t.id!==e.id&&this.tablesSelectionFormOutlet.visible(t.id,!1),this.tablesSelectionFormOutlet.visible(e.id,!0),this.checkedValue=this.tablesSelectionFormOutlet.isSelected(e.id),this.update())}checkedValueChanged(){this.hasTablesSelectionFormOutlet&&(this.checkedValue=this.tablesSelectionFormOutlet.isSelected(this.id),this.update())}async update(){return this.updating||=Promise.resolve().then((()=>{this.#t(),delete this.updating})),this.updating}#t(){this.element.querySelector("input").checked=this.checkedValue,this.dispatch("select",{detail:{id:this.id,selected:this.checkedValue}})}}class i{constructor(){this.tokens=[],this.values=null}parse(e){const t=new u(e);for(;!t.isEos();){this.push(this.skipWhitespace(t));const e=this.takeTagged(t)||this.takeUntagged(t);if(!this.push(e))break}return this}push(e){return e&&(this.values?this.values.push(e):this.tokens.push(e)),!!e}skipWhitespace(e){if(e.scan(/\s+/))return new n(e.matched(),e.position)}takeUntagged(e){if(e.scan(/\S+/))return new l(e.matched(),e.position)}takeTagged(e){if(!e.scan(/(\w+(?:\.\w+)?)(:\s*)/))return;const t=e.valueAt(1),s=e.valueAt(2),i=this.takeArrayValue(e)||this.takeSingleValue(e)||new n;return new r(t,s,i,e.position)}takeArrayValue(e){if(!e.scan(/\[\s*/))return;const t=new n(e.matched(),e.position),s=this.values=[];for(;!e.isEos()&&this.push(this.takeSingleValue(e))&&this.push(this.takeDelimiter(e)););e.scan(/\s*]/);const i=new n(e.matched(),e.position);return this.values=null,new o(t,s,i)}takeDelimiter(e){if(e.scan(/\s*,\s*/))return new n(e.matched(),e.position)}takeSingleValue(e){return this.takeQuotedValue(e)||this.takeUnquotedValue(e)}takeQuotedValue(e){if(e.scan(/"([^"]*)"/))return new a(e.matched(),e.position)}takeUnquotedValue(e){if(e.scan(/[^ \],]*/))return new a(e.matched(),e.position)}tokenAtPosition(e){return this.tokens.filter((e=>e instanceof r||e instanceof l)).find((t=>t.range.includes(e)))}}class n{constructor(e="",t){this.value=e,this.length=this.value.length,this.start=t-this.length,this.end=this.start+this.length,this.range=this.arrayRange(this.start,this.end)}render(){return document.createTextNode(this.value)}arrayRange(e,t){return Array.from({length:t-e+1},((t,s)=>e+s))}startOfValue(){return this.start}endOfValue(){return this.end}}class a extends n{render(){const e=document.createElement("span");return e.className="value",e.innerText=this.value,e}}class r extends n{constructor(e,t,s,i){super(),this.key=e,this.separator=t,this.value=s,this.length=e.length+t.length+s.value.length,this.start=i-this.length,this.end=this.start+this.length,this.range=this.arrayRange(this.start,this.end)}render(){const e=document.createElement("span");e.className="tag";const t=document.createElement("span");return t.className="key",t.innerText=this.key,e.appendChild(t),e.appendChild(document.createTextNode(this.separator)),e.appendChild(this.value.render()),e}startOfValue(){return this.value.startOfValue()}endOfValue(){return this.value.endOfValue()}}class l extends n{render(){const e=document.createElement("span");return e.className="untagged",e.innerText=this.value,e}}class o extends n{constructor(e,t,s){super(),this.start=e,this.values=t,this.end=s,this.range=this.arrayRange(e.start,s.range[s.length]),this.length=e.length+t.reduce(((e,t)=>e+t.length),0)+s.length}render(){const e=document.createElement("span");return e.className="array-values",e.appendChild(this.start.render()),this.values.forEach((t=>{const s=document.createElement("span");s.appendChild(t.render()),e.appendChild(s)})),e.appendChild(this.end.render()),e}startOfValue(){return this.start.start}endOfValue(){return this.end.end}}class u{constructor(e){this.input=e,this.position=0,this.last=null}isEos(){return this.position>=this.input.length}scan(e){const t=e.exec(this.input.substring(this.position));return 0===t?.index?(this.last=t,this.position+=t[0].length,!0):(this.last={},!1)}matched(){return this.last&&this.last[0]}valueAt(e){return this.last&&this.last[e]}}const h=[{identifier:"tables--orderable--item",controllerConstructor:class extends e{static values={params:Object};connect(){var e;this.index=(e=this.row,Array.from(e.parentElement.children).indexOf(e))}paramsValueChanged(e){this.id=e.id_value}dragUpdate(e){this.dragOffset=e,this.row.style.position="relative",this.row.style.top=e+"px",this.row.style.zIndex="1",this.row.toggleAttribute("dragging",!0)}updateVisually(e){this.row.style.position="relative",this.row.style.top=this.row.offsetHeight*(e-this.dragIndex)+"px"}updateIndex(e){this.index=e}params(e){const{id_name:t,id_value:s,index_name:i}=this.paramsValue;return[{name:`${e}[${s}][${t}]`,value:this.id},{name:`${e}[${s}][${i}]`,value:this.index}]}reset(){delete this.dragOffset,this.row.removeAttribute("style"),this.row.removeAttribute("dragging")}get hasChanges(){return this.paramsValue.index_value!==this.index}get dragIndex(){return this.dragOffset&&0!==this.dragOffset?this.index+Math.round(this.dragOffset/this.row.offsetHeight):this.index}get comparisonIndex(){return this.dragOffset?this.dragIndex+(this.dragOffset>0?.5:-.5):this.index}get row(){return this.element.parentElement}}},{identifier:"tables--orderable--list",controllerConstructor:class extends e{static outlets=["tables--orderable--item","tables--orderable--form"];startDragging(e){this.dragState=e,document.addEventListener("mousemove",this.mousemove),document.addEventListener("mouseup",this.mouseup),window.addEventListener("scroll",this.scroll,!0),this.element.style.position="relative"}stopDragging(){const e=this.dragState;return delete this.dragState,document.removeEventListener("mousemove",this.mousemove),document.removeEventListener("mouseup",this.mouseup),window.removeEventListener("scroll",this.scroll,!0),this.element.removeAttribute("style"),this.tablesOrderableItemOutlets.forEach((e=>e.reset())),e}drop(){const e=this.dragItem;if(!e)return;const t=e.dragIndex,s=this.tablesOrderableItemOutlets[t];s&&(t<e.index?s.row.insertAdjacentElement("beforebegin",e.row):t>e.index&&s.row.insertAdjacentElement("afterend",e.row),this.tablesOrderableItemOutlets.forEach(((e,t)=>e.updateIndex(t))),this.commitChanges())}commitChanges(){this.tablesOrderableFormOutlet.clear(),this.tablesOrderableItemOutlets.forEach((e=>{e.hasChanges&&this.tablesOrderableFormOutlet.add(e)})),this.tablesOrderableFormOutlet.submit()}mousedown(e){if(this.isDragging)return;const s=this.#s(e.target);s&&(e.preventDefault(),this.startDragging(new t(this.element,e,s.id)),this.dragState.updateCursor(this.element,s.row,e,this.animate))}mousemove=e=>{this.isDragging&&(e.preventDefault(),this.ticking||(this.ticking=!0,window.requestAnimationFrame((()=>{this.ticking=!1,this.dragState?.updateCursor(this.element,this.dragItem.row,e,this.animate)}))))};scroll=e=>{this.isDragging&&!this.ticking&&(this.ticking=!0,window.requestAnimationFrame((()=>{this.ticking=!1,this.dragState?.updateScroll(this.element,this.dragItem.row,this.animate)})))};mouseup=e=>{this.isDragging&&(this.drop(),this.stopDragging(),this.tablesOrderableFormOutlets.forEach((e=>delete e.dragState)))};tablesOrderableFormOutletConnected(e,t){e.dragState&&this.startDragging(e.dragState)}tablesOrderableFormOutletDisconnected(e,t){this.isDragging&&(e.dragState=this.stopDragging())}beforeMorphAttribute(e){switch(e.detail.attributeName){case"dragging":e.preventDefault();break;case"style":"TBODY"!==e.target.tagName&&"TR"!==e.target.tagName||e.preventDefault()}}animate=e=>{const t=this.dragItem;t.dragUpdate(e),this.#i.forEach(((e,s)=>{e!==t&&e.updateVisually(s)}))};get isDragging(){return!!this.dragState}get dragItem(){return this.isDragging?this.tablesOrderableItemOutlets.find((e=>e.id===this.dragState.targetId)):null}get#i(){return this.tablesOrderableItemOutlets.toSorted(((e,t)=>e.comparisonIndex-t.comparisonIndex))}#s(e){return this.tablesOrderableItemOutlets.find((t=>t.element===e))}}},{identifier:"tables--orderable--form",controllerConstructor:class extends e{static values={scope:String};add(e){e.params(this.scopeValue).forEach((({name:e,value:t})=>{this.element.insertAdjacentHTML("beforeend",`<input type="hidden" name="${e}" value="${t}" data-generated>`)}))}submit(){0!==this.inputs.length&&this.element.requestSubmit()}clear(){this.inputs.forEach((e=>e.remove()))}get inputs(){return this.element.querySelectorAll("input[data-generated]")}}},{identifier:"tables--selection--form",controllerConstructor:class extends e{static values={count:Number,primaryKey:{type:String,default:"id"}};static targets=["count","singular","plural"];connect(){this.countValue=this.inputs.length}toggle(e){const t=this.input(e);return t?t.remove():this.element.insertAdjacentHTML("beforeend",`<input type="hidden" name="${this.primaryKeyValue}[]" value="${e}">`),this.countValue=this.visibleInputs.length,!t}visible(e,t){const s=this.input(e);return s&&(s.disabled=!t),this.countValue=this.visibleInputs.length,!s}isSelected(e){return!!this.input(e)}get inputs(){return this.element.querySelectorAll(`input[name="${this.primaryKeyValue}[]"]`)}get visibleInputs(){return Array.from(this.inputs).filter((e=>!e.disabled))}input(e){return this.element.querySelector(`input[name="${this.primaryKeyValue}[]"][value="${e}"]`)}countValueChanged(e){this.element.toggleAttribute("hidden",0===e),this.countTarget.textContent=e,this.singularTarget.toggleAttribute("hidden",1!==e),this.pluralTarget.toggleAttribute("hidden",1===e)}}},{identifier:"tables--selection--item",controllerConstructor:s},{identifier:"tables--selection--table",controllerConstructor:class extends e{static targets=["header","item"];static outlets=["tables--selection--form"];itemTargetConnected(e){this.update()}itemTargetDisconnected(e){this.update()}toggleHeader(e){this.items.forEach((t=>{t.checkedValue!==e.target.checked&&(t.checkedValue=this.tablesSelectionFormOutlet.toggle(t.id))}))}async update(){return this.updating||=Promise.resolve().then((()=>{this.#t(),delete this.updating})),this.updating}#t(){let e=0,t=0;this.items.forEach((s=>{e++,s.checkedValue&&t++})),this.headerInput.checked=e>0&&t===e,this.headerInput.indeterminate=t>0&&t!==e}get headerInput(){return this.headerTarget.querySelector("input")}get items(){return this.itemTargets.map((e=>this.#n(e))).filter((e=>e))}#n(e){return this.application.getControllerForElementAndIdentifier(e,"tables--selection--item")}}},{identifier:"tables--query",controllerConstructor:class extends e{static targets=["modal"];disconnect(){delete this.pending,document.removeEventListener("selectionchange",this.selection)}focus(){document.activeElement!==this.query&&(this.query.addEventListener("focusin",(e=>{e.target.setSelectionRange(-1,-1)}),{once:!0}),this.query.focus())}closeModal(){delete this.modalTarget.dataset.open,this.query.setAttribute("aria-expanded",!1),document.activeElement===this.query&&document.activeElement.blur(),document.removeEventListener("selectionchange",this.selection)}openModal(){this.modalTarget.dataset.open=!0,this.query.setAttribute("aria-expanded",!0),document.addEventListener("selectionchange",this.selection)}clear(){""===this.query.value?this.closeModal():(this.query.value="",this.query.dispatchEvent(new Event("input")),this.query.dispatchEvent(new Event("change")),this.update())}submit(){const e=this.isFocused,t=e&&this.query.selectionStart;this.pending&&(clearTimeout(this.pending),delete this.pending),e&&""!==this.query.value?(this.position.value=t,this.position.disabled=!1):(this.position.value="",this.position.disabled=!0),""===this.query.value&&(this.query.disabled=!0,setTimeout((()=>{this.query.disabled=!1,this.position.disabled=!1,e&&this.query.focus()}),0))}update=()=>{this.pending&&clearTimeout(this.pending),this.pending=setTimeout((()=>{this.element.requestSubmit()}),300)};selection=()=>{this.isFocused&&this.query.value.length>0&&this.update()};beforeMorphAttribute(e){if("data-open"===e.detail.attributeName)e.preventDefault()}moveToPreviousSuggestion(){const e=this.previousSuggestion||this.lastSuggestion;e&&this.makeSuggestionActive(e)}moveToNextSuggestion(){const e=this.nextSuggestion||this.firstSuggestion;e&&this.makeSuggestionActive(e)}selectFirstSuggestion(e){e.preventDefault(),this.firstSuggestion?.dispatchEvent(new CustomEvent("query:select"))}selectActiveSuggestion(){this.activeSuggestion?this.activeSuggestion.dispatchEvent(new CustomEvent("query:select")):this.closeModal()}selectSuggestion(e){this.query.dispatchEvent(new CustomEvent("replaceToken",{detail:{token:e.params.value,position:this.query.selectionStart}})),this.clearActiveSuggestion()}makeSuggestionActive(e){this.activeSuggestion&&this.activeSuggestion.setAttribute("aria-selected","false"),this.query.setAttribute("aria-activedescendant",e.id),e.setAttribute("aria-selected","true")}clearActiveSuggestion(){this.activeSuggestion&&(this.activeSuggestion.setAttribute("aria-selected","false"),this.query.removeAttribute("aria-activedescendant"))}get activeSuggestion(){return this.modalTarget.querySelector(`#${this.query.getAttribute("aria-activedescendant")}`)}get previousSuggestion(){return this.activeSuggestion?.previousElementSibling}get nextSuggestion(){return this.activeSuggestion?.nextElementSibling}get firstSuggestion(){return this.modalTarget.querySelector("#suggestions li:first-of-type")}get lastSuggestion(){return this.modalTarget.querySelector("#suggestions li:last-of-type")}get query(){return this.element.querySelector("[role=combobox]")}get position(){return this.element.querySelector("input[name=p]")}get isFocused(){return this.query===document.activeElement}}},{identifier:"tables--query-input",controllerConstructor:class extends e{static targets=["input","highlight"];static values={query:String};connect(){this.queryValue=this.inputTarget.value,this.element.dataset.connected=""}disconnect(){delete this.element.dataset.connected}update(){this.queryValue=this.inputTarget.value}queryValueChanged(e){this.highlightTarget.innerHTML="",(new i).parse(e).tokens.forEach((e=>{this.highlightTarget.appendChild(e.render())}))}replaceToken(e){let t=e.detail.token.toString();/\s/.exec(t)&&(t=`"${t}"`);const s=e.detail.position;let n=s+t.length,a=s,r=s;const l=(new i).parse(this.queryValue).tokenAtPosition(s);l&&(t=t.trim(),a=l.startOfValue(),r=l.endOfValue(),n=a+t.length),this.inputTarget.value=this.queryValue.slice(0,a)+t+this.queryValue.slice(r),this.update(),this.inputTarget.focus(),this.inputTarget.setSelectionRange(n,n)}}}];export{h as default};
|
2
2
|
//# sourceMappingURL=tables.min.js.map
|