@gardenerim/css 1.0.0 → 2.0.0
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/CHANGELOG.md +10 -2
- package/LICENSE +1 -1
- package/README.md +9 -9
- package/dist/components/ai-compositions.min.css +1 -1
- package/dist/components/ai-extended.min.css +1 -1
- package/dist/components/ai.min.css +1 -1
- package/dist/components/auth-compositions.min.css +1 -1
- package/dist/components/basic.min.css +1 -1
- package/dist/components/catalog.min.css +1 -1
- package/dist/components/commerce-compositions.min.css +1 -1
- package/dist/components/content-compositions.min.css +1 -1
- package/dist/components/data-compositions.min.css +1 -1
- package/dist/components/data.min.css +1 -1
- package/dist/components/desktop-compositions.min.css +1 -1
- package/dist/components/desktop.min.css +1 -1
- package/dist/components/extended.min.css +1 -1
- package/dist/components/feedback.min.css +1 -1
- package/dist/components/form-compositions.min.css +1 -1
- package/dist/components/forms.min.css +1 -1
- package/dist/components/grid.min.css +1 -1
- package/dist/components/help.min.css +1 -1
- package/dist/components/layouts.min.css +1 -1
- package/dist/components/mobile-compositions.min.css +1 -1
- package/dist/components/navigation-compositions.min.css +1 -1
- package/dist/components/navigation.min.css +1 -1
- package/dist/components/page.min.css +1 -1
- package/dist/components/primitives.min.css +1 -1
- package/dist/components/recipes.min.css +1 -1
- package/dist/components/regions.min.css +1 -1
- package/dist/components/selection-compositions.min.css +1 -1
- package/dist/components/solution-compositions.min.css +1 -1
- package/dist/gardener.ai.css +1 -1
- package/dist/gardener.ai.min.css +1 -1
- package/dist/gardener.builds.json +302 -302
- package/dist/gardener.compatibility.json +2 -2
- package/dist/gardener.components.css +1 -1
- package/dist/gardener.components.min.css +1 -1
- package/dist/gardener.core.css +1 -1
- package/dist/gardener.core.min.css +1 -1
- package/dist/gardener.css +1 -1
- package/dist/gardener.d.ts +93 -26
- package/dist/gardener.electron.d.ts +5 -5
- package/dist/gardener.electron.min.js +1 -1
- package/dist/gardener.manifest.json +2 -2
- package/dist/gardener.min.css +1 -1
- package/dist/gardener.performance.json +378 -378
- package/dist/gardener.public-api.json +34 -10
- package/dist/gardener.runtime.js +173 -7
- package/dist/gardener.runtime.min.js +2 -2
- package/dist/gardener.runtime.min.js.map +3 -3
- package/dist/gardener.tauri.d.ts +5 -5
- package/dist/gardener.tauri.js +1 -1
- package/dist/gardener.tauri.min.js +1 -1
- package/dist/gardener.tauri.min.js.map +1 -1
- package/dist/gardener.themes.css +1 -1
- package/dist/gardener.themes.min.css +1 -1
- package/dist/gardener.utilities.css +1 -1
- package/dist/gardener.utilities.min.css +1 -1
- package/dist/platforms/gardener.desktop.min.css +1 -1
- package/dist/platforms/gardener.electron.min.css +1 -1
- package/dist/platforms/gardener.mobile.min.css +1 -1
- package/dist/platforms/gardener.tauri.min.css +1 -1
- package/dist/platforms/gardener.web.min.css +1 -1
- package/metadata/builds.schema.json +1 -1
- package/metadata/capabilities.schema.json +1 -1
- package/metadata/compatibility.json +2 -2
- package/metadata/compatibility.schema.json +1 -1
- package/metadata/components.schema.json +1 -1
- package/metadata/custom-build.schema.json +1 -1
- package/metadata/manifest.schema.json +2 -2
- package/metadata/performance-budgets.schema.json +2 -1
- package/metadata/performance-report.schema.json +1 -1
- package/metadata/public-api.json +36 -12
- package/metadata/public-api.schema.json +1 -1
- package/metadata/recipes.schema.json +1 -1
- package/metadata/utilities.schema.json +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "../metadata/public-api.schema.json",
|
|
3
3
|
"schemaVersion": 1,
|
|
4
|
-
"contractVersion": "
|
|
4
|
+
"contractVersion": "2.0.0",
|
|
5
5
|
"status": "stable",
|
|
6
6
|
"naming": {
|
|
7
7
|
"cssClassPrefix": "g-",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"javascript": {
|
|
59
59
|
"moduleExports": [
|
|
60
60
|
"default",
|
|
61
|
-
"
|
|
61
|
+
"Gardenerim",
|
|
62
62
|
"init",
|
|
63
63
|
"destroy",
|
|
64
64
|
"register",
|
|
@@ -72,15 +72,15 @@
|
|
|
72
72
|
"name": "default",
|
|
73
73
|
"kind": "object",
|
|
74
74
|
"parameters": [],
|
|
75
|
-
"returns": "Readonly<
|
|
76
|
-
"signature": "default: Readonly<
|
|
75
|
+
"returns": "Readonly<GardenerimAPI>",
|
|
76
|
+
"signature": "default: Readonly<GardenerimAPI>"
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
|
-
"name": "
|
|
79
|
+
"name": "Gardenerim",
|
|
80
80
|
"kind": "object",
|
|
81
81
|
"parameters": [],
|
|
82
|
-
"returns": "Readonly<
|
|
83
|
-
"signature": "
|
|
82
|
+
"returns": "Readonly<GardenerimAPI>",
|
|
83
|
+
"signature": "Gardenerim: Readonly<GardenerimAPI>"
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
86
|
"name": "init",
|
|
@@ -88,8 +88,8 @@
|
|
|
88
88
|
"parameters": [
|
|
89
89
|
"root = document"
|
|
90
90
|
],
|
|
91
|
-
"returns": "
|
|
92
|
-
"signature": "init(root = document) =>
|
|
91
|
+
"returns": "Gardenerim",
|
|
92
|
+
"signature": "init(root = document) => Gardenerim"
|
|
93
93
|
},
|
|
94
94
|
{
|
|
95
95
|
"name": "destroy",
|
|
@@ -603,7 +603,17 @@
|
|
|
603
603
|
"attribute": "data-g-data-grid",
|
|
604
604
|
"instanceMembers": [
|
|
605
605
|
"focus",
|
|
606
|
-
"destroy"
|
|
606
|
+
"destroy",
|
|
607
|
+
"refresh",
|
|
608
|
+
"setOptions",
|
|
609
|
+
"setRows",
|
|
610
|
+
"setPage",
|
|
611
|
+
"setSort",
|
|
612
|
+
"setFilter",
|
|
613
|
+
"select",
|
|
614
|
+
"getState",
|
|
615
|
+
"updateCell",
|
|
616
|
+
"load"
|
|
607
617
|
]
|
|
608
618
|
},
|
|
609
619
|
{
|
|
@@ -1118,6 +1128,19 @@
|
|
|
1118
1128
|
"step",
|
|
1119
1129
|
"source",
|
|
1120
1130
|
"item",
|
|
1131
|
+
"reason",
|
|
1132
|
+
"page",
|
|
1133
|
+
"pageSize",
|
|
1134
|
+
"total",
|
|
1135
|
+
"sort",
|
|
1136
|
+
"filter",
|
|
1137
|
+
"selectedKeys",
|
|
1138
|
+
"loading",
|
|
1139
|
+
"error",
|
|
1140
|
+
"key",
|
|
1141
|
+
"field",
|
|
1142
|
+
"previous",
|
|
1143
|
+
"row",
|
|
1121
1144
|
"link",
|
|
1122
1145
|
"section",
|
|
1123
1146
|
"target"
|
|
@@ -1859,6 +1882,7 @@
|
|
|
1859
1882
|
"data-g-filter-input",
|
|
1860
1883
|
"data-g-filter-item",
|
|
1861
1884
|
"data-g-filter-previous-hidden",
|
|
1885
|
+
"data-g-grid-viewport",
|
|
1862
1886
|
"data-g-group-row",
|
|
1863
1887
|
"data-g-infinite-load-more",
|
|
1864
1888
|
"data-g-infinite-sentinel",
|
package/dist/gardener.runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/** Gardenerim runtime v2.0.0 — framework-agnostic, accessible component behavior. */
|
|
2
2
|
|
|
3
3
|
const instanceStores = new WeakMap();
|
|
4
4
|
const registry = new Map();
|
|
@@ -825,10 +825,171 @@ function createTree(element) {
|
|
|
825
825
|
}
|
|
826
826
|
|
|
827
827
|
function createDataGrid(element) {
|
|
828
|
+
// Markup-only mode remains compatible. Data ownership starts only when the
|
|
829
|
+
// consumer explicitly calls setOptions({ columns, rows/load }).
|
|
830
|
+
let options = {}, rows = [], columns = [], selected = new Set(), page = 1;
|
|
831
|
+
let pageSize = 20, sort = null, filter = "", total = 0, loading = false, error = "";
|
|
832
|
+
let viewport, table, body, footer, managed = false, disposed = false, request = 0, abort;
|
|
833
|
+
let originalChildren = null, scrollHandler = null;
|
|
834
|
+
const focusIds = new WeakMap();
|
|
835
|
+
const identify = (node, id) => { focusIds.set(node, JSON.stringify(id)); return node; };
|
|
836
|
+
const make = (tag, text) => { const node = document.createElement(tag); if (text != null) node.textContent = String(text); return node; };
|
|
837
|
+
const keyOf = (row) => row[options.rowKey || "id"];
|
|
838
|
+
const safeField = (field) => typeof field === "string" && !["__proto__", "prototype", "constructor"].includes(field);
|
|
839
|
+
const announce = (reason, extra = {}) => {
|
|
840
|
+
const detail = { reason, ...getState(), ...extra };
|
|
841
|
+
emit(element, "change", { reason: detail.reason, page: detail.page, pageSize: detail.pageSize, total: detail.total, sort: detail.sort, filter: detail.filter, selectedKeys: detail.selectedKeys, loading: detail.loading, error: detail.error, key: detail.key, field: detail.field, value: detail.value, previous: detail.previous, row: detail.row });
|
|
842
|
+
options.onChange?.(detail);
|
|
843
|
+
};
|
|
844
|
+
const filteredRows = () => {
|
|
845
|
+
if (options.mode === "server") return rows;
|
|
846
|
+
const query = filter.trim().toLocaleLowerCase();
|
|
847
|
+
const result = query ? rows.filter(row => columns.some(column => String(row[column.field] ?? "").toLocaleLowerCase().includes(query))) : [...rows];
|
|
848
|
+
if (sort) {
|
|
849
|
+
const column = columns.find(column => column.field === sort.field);
|
|
850
|
+
const compare = new Intl.Collator(options.locale, { numeric: true, sensitivity: "base" });
|
|
851
|
+
result.sort((a, b) => {
|
|
852
|
+
const left = a[sort.field], right = b[sort.field];
|
|
853
|
+
const value = column?.type === "number" ? numeric(left, 0) - numeric(right, 0) : compare.compare(String(left ?? ""), String(right ?? ""));
|
|
854
|
+
return sort.direction === "desc" ? -value : value;
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
return result;
|
|
858
|
+
};
|
|
859
|
+
function getState() {
|
|
860
|
+
return { page, pageSize, total, sort: sort ? { ...sort } : null, filter, selectedKeys: [...selected], loading, error };
|
|
861
|
+
}
|
|
862
|
+
function refresh() {
|
|
863
|
+
if (!managed || disposed) return;
|
|
864
|
+
const focused = document.activeElement, focusId = focusIds.get(focused);
|
|
865
|
+
const selection = focused?.selectionStart == null ? null : [focused.selectionStart, focused.selectionEnd];
|
|
866
|
+
const filtered = filteredRows();
|
|
867
|
+
total = options.mode === "server" ? total : filtered.length;
|
|
868
|
+
if (options.mode !== "server") page = Math.max(1, Math.min(page, Math.max(1, Math.ceil(total / pageSize))));
|
|
869
|
+
const pageRows = options.mode === "server" ? filtered : filtered.slice((page - 1) * pageSize, page * pageSize);
|
|
870
|
+
const rowHeight = Math.max(24, numeric(options.rowHeight, 40));
|
|
871
|
+
const height = Math.max(rowHeight, numeric(options.height, 400));
|
|
872
|
+
const virtual = options.virtual === true;
|
|
873
|
+
const start = virtual ? Math.min(Math.max(0, pageRows.length - 1), Math.max(0, Math.floor(viewport.scrollTop / rowHeight) - 3)) : 0;
|
|
874
|
+
const end = virtual ? Math.min(pageRows.length, start + Math.ceil(height / rowHeight) + 6) : pageRows.length;
|
|
875
|
+
const head = make("thead"), header = make("tr"); header.setAttribute("role", "row");
|
|
876
|
+
if (options.selectable) { const th = make("th", options.labels?.select || "选择"); th.setAttribute("scope", "col"); header.append(th); }
|
|
877
|
+
for (const column of columns) {
|
|
878
|
+
const th = make("th"); th.setAttribute("role", "columnheader"); th.setAttribute("scope", "col");
|
|
879
|
+
th.setAttribute("aria-sort", sort?.field === column.field ? sort.direction === "asc" ? "ascending" : "descending" : "none");
|
|
880
|
+
if (column.sortable !== false) {
|
|
881
|
+
const button = make("button", column.title || column.field); button.type = "button"; button.className = "g-btn g-btn-ghost";
|
|
882
|
+
identify(button, ["sort", column.field]);
|
|
883
|
+
button.addEventListener("click", () => setSort(column.field, sort?.field === column.field && sort.direction === "asc" ? "desc" : "asc")); th.append(button);
|
|
884
|
+
} else th.textContent = column.title || column.field;
|
|
885
|
+
header.append(th);
|
|
886
|
+
}
|
|
887
|
+
head.append(header); table.tHead?.remove(); table.prepend(head);
|
|
888
|
+
body.replaceChildren();
|
|
889
|
+
const span = columns.length + (options.selectable ? 1 : 0);
|
|
890
|
+
const spacer = size => { if (size <= 0) return; const tr = make("tr"), td = make("td"); tr.setAttribute("aria-hidden", "true"); td.colSpan = span; td.style.cssText = `height:${size}px;padding:0;border:0`; tr.append(td); body.append(tr); };
|
|
891
|
+
spacer(start * rowHeight);
|
|
892
|
+
for (let index = start; index < end; index++) {
|
|
893
|
+
const row = pageRows[index], key = keyOf(row), tr = make("tr");
|
|
894
|
+
tr.setAttribute("role", "row"); tr.setAttribute("aria-rowindex", String((page - 1) * pageSize + index + 2));
|
|
895
|
+
if (virtual) tr.style.height = `${rowHeight}px`;
|
|
896
|
+
if (options.selectable) {
|
|
897
|
+
tr.setAttribute("aria-selected", String(selected.has(key)));
|
|
898
|
+
const td = make("td"), checkbox = make("input"); checkbox.type = "checkbox"; checkbox.checked = selected.has(key);
|
|
899
|
+
td.setAttribute("role", "gridcell"); identify(checkbox, ["select", key]);
|
|
900
|
+
checkbox.setAttribute("aria-label", `${options.labels?.select || "选择"} ${key}`);
|
|
901
|
+
checkbox.addEventListener("change", () => select(key, checkbox.checked)); td.append(checkbox); tr.append(td);
|
|
902
|
+
}
|
|
903
|
+
for (const column of columns) {
|
|
904
|
+
const td = make("td"); td.setAttribute("role", "gridcell"); td.tabIndex = -1;
|
|
905
|
+
if (column.editable) {
|
|
906
|
+
const input = make("input"); input.type = column.type === "number" ? "number" : "text";
|
|
907
|
+
identify(input, ["edit", key, column.field]);
|
|
908
|
+
input.className = "g-input"; input.value = String(row[column.field] ?? "");
|
|
909
|
+
input.setAttribute("aria-label", `${column.title || column.field} ${key}`);
|
|
910
|
+
input.addEventListener("change", () => updateCell(key, column.field, column.type === "number" ? Number(input.value) : input.value)); td.append(input);
|
|
911
|
+
} else td.textContent = String(column.format ? column.format(row[column.field], row) : row[column.field] ?? "");
|
|
912
|
+
if (virtual) { td.style.height = `${rowHeight}px`; td.style.paddingBlock = "0"; td.style.whiteSpace = "nowrap"; td.style.overflow = "hidden"; }
|
|
913
|
+
tr.append(td);
|
|
914
|
+
}
|
|
915
|
+
body.append(tr);
|
|
916
|
+
}
|
|
917
|
+
spacer((pageRows.length - end) * rowHeight);
|
|
918
|
+
if (!pageRows.length) { const tr = make("tr"), td = make("td", error || (loading ? options.labels?.loading || "加载中…" : options.labels?.empty || "暂无数据")); td.colSpan = span; tr.append(td); body.append(tr); }
|
|
919
|
+
table.setAttribute("aria-rowcount", String(total + 1)); table.setAttribute("aria-colcount", String(span));
|
|
920
|
+
element.setAttribute("aria-busy", String(loading)); element.classList.toggle("is-loading", loading); element.classList.toggle("is-error", !!error); element.classList.toggle("is-empty", total === 0 && !loading);
|
|
921
|
+
viewport.style.maxHeight = `${height}px`; viewport.style.overflow = "auto";
|
|
922
|
+
footer.replaceChildren();
|
|
923
|
+
const previous = make("button", options.labels?.previous || "上一页"), next = make("button", options.labels?.next || "下一页");
|
|
924
|
+
identify(previous, ["page", "previous"]); identify(next, ["page", "next"]);
|
|
925
|
+
previous.type = next.type = "button"; previous.className = next.className = "g-btn";
|
|
926
|
+
previous.disabled = page <= 1 || loading; next.disabled = page * pageSize >= total || loading;
|
|
927
|
+
previous.addEventListener("click", () => setPage(page - 1)); next.addEventListener("click", () => setPage(page + 1));
|
|
928
|
+
footer.append(previous, make("span", ` ${page} / ${Math.max(1, Math.ceil(total / pageSize))} · ${total} `), next);
|
|
929
|
+
const first = cells()[0]; if (first) first.tabIndex = 0;
|
|
930
|
+
if (focusId) {
|
|
931
|
+
const replacement = [...element.querySelectorAll("input,button")].find(node => focusIds.get(node) === focusId);
|
|
932
|
+
if (replacement && !replacement.disabled) { replacement.focus({ preventScroll: true }); if (selection && replacement.setSelectionRange) replacement.setSelectionRange(...selection); }
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
function setRows(next, count) {
|
|
936
|
+
if (!Array.isArray(next)) throw new TypeError("DataGrid rows must be an array");
|
|
937
|
+
const keys = new Set();
|
|
938
|
+
for (const row of next) { const key = row && keyOf(row); if (!["string", "number"].includes(typeof key) || keys.has(key)) throw new TypeError("DataGrid requires unique string/number row keys"); keys.add(key); }
|
|
939
|
+
rows = next.map(row => ({ ...row })); total = options.mode === "server" ? Math.max(0, numeric(count, rows.length)) : rows.length;
|
|
940
|
+
refresh(); return getState();
|
|
941
|
+
}
|
|
942
|
+
async function load() {
|
|
943
|
+
if (disposed || options.mode !== "server" || typeof options.load !== "function") { refresh(); return getState(); }
|
|
944
|
+
abort?.abort(); abort = new AbortController(); const id = ++request;
|
|
945
|
+
loading = true; error = ""; refresh();
|
|
946
|
+
try {
|
|
947
|
+
const result = await options.load({ page, pageSize, sort: sort ? { ...sort } : null, filter, signal: abort.signal });
|
|
948
|
+
if (disposed || id !== request) return getState();
|
|
949
|
+
loading = false; setRows(result.rows, result.total); announce("load");
|
|
950
|
+
} catch (exception) {
|
|
951
|
+
if (!disposed && id === request && !abort.signal.aborted) { loading = false; error = String(exception?.message || exception); refresh(); announce("error"); }
|
|
952
|
+
}
|
|
953
|
+
return getState();
|
|
954
|
+
}
|
|
955
|
+
function queryChanged(reason) { if (viewport) viewport.scrollTop = 0; refresh(); announce(reason); return options.mode === "server" ? load() : getState(); }
|
|
956
|
+
function setPage(value, size = pageSize) { page = Math.max(1, Math.floor(numeric(value, 1))); pageSize = Math.max(1, Math.floor(numeric(size, 20))); return queryChanged("page"); }
|
|
957
|
+
function setSort(field, direction = "asc") { if (field != null && !columns.some(column => column.field === field)) throw new TypeError("Unknown DataGrid column"); sort = field == null ? null : { field, direction: direction === "desc" ? "desc" : "asc" }; page = 1; return queryChanged("sort"); }
|
|
958
|
+
function setFilter(value) { filter = String(value ?? ""); page = 1; return queryChanged("filter"); }
|
|
959
|
+
function select(key, checked = true) { if (checked) selected.add(key); else selected.delete(key); refresh(); announce("selection"); return [...selected]; }
|
|
960
|
+
function updateCell(key, field, value) {
|
|
961
|
+
const column = columns.find(column => column.field === field), index = rows.findIndex(row => keyOf(row) === key);
|
|
962
|
+
if (index < 0 || !column?.editable || !safeField(field) || field === (options.rowKey || "id")) throw new TypeError("DataGrid cell is not editable");
|
|
963
|
+
if (column.type === "number" && !Number.isFinite(Number(value))) throw new TypeError("DataGrid number must be finite");
|
|
964
|
+
if (column.type === "number") value = Number(value);
|
|
965
|
+
const previous = rows[index][field]; rows[index] = { ...rows[index], [field]: value }; refresh();
|
|
966
|
+
announce("edit", { key, field, value, previous, row: { ...rows[index] } }); return { ...rows[index] };
|
|
967
|
+
}
|
|
968
|
+
function setOptions(next) {
|
|
969
|
+
if (disposed) throw new Error("DataGrid has been destroyed");
|
|
970
|
+
if (!next || !Array.isArray(next.columns) || !next.columns.length || next.columns.some(column => !safeField(column.field))) throw new TypeError("DataGrid requires safe columns");
|
|
971
|
+
if (new Set(next.columns.map(column => column.field)).size !== next.columns.length) throw new TypeError("DataGrid column fields must be unique");
|
|
972
|
+
abort?.abort(); request++; loading = false; error = "";
|
|
973
|
+
options = { ...next }; columns = next.columns.map(column => ({ ...column }));
|
|
974
|
+
page = Math.max(1, Math.floor(numeric(next.page, 1))); pageSize = Math.max(1, Math.floor(numeric(next.pageSize, 20)));
|
|
975
|
+
selected = new Set(next.selectedKeys || []); sort = next.sort || null; filter = String(next.filter || "");
|
|
976
|
+
if (!managed) {
|
|
977
|
+
originalChildren = [...element.childNodes]; element.replaceChildren();
|
|
978
|
+
viewport = make("div"); viewport.setAttribute("data-g-grid-viewport", ""); table = make("table"); table.className = "g-table"; table.setAttribute("role", "grid");
|
|
979
|
+
element.setAttribute("role", "region");
|
|
980
|
+
table.setAttribute("aria-label", element.getAttribute("aria-label") || "数据网格");
|
|
981
|
+
if (element.hasAttribute("aria-labelledby")) table.setAttribute("aria-labelledby", element.getAttribute("aria-labelledby"));
|
|
982
|
+
body = make("tbody"); table.append(body); viewport.append(table); footer = make("div"); footer.className = "g-pagination";
|
|
983
|
+
element.append(viewport, footer); managed = true;
|
|
984
|
+
scrollHandler = () => { if (options.virtual) refresh(); }; viewport.addEventListener("scroll", scrollHandler);
|
|
985
|
+
}
|
|
986
|
+
setRows(next.rows || [], next.total); if (options.mode === "server" && options.load) void load(); return getState();
|
|
987
|
+
}
|
|
828
988
|
const cells = () => [...element.querySelectorAll("[role='gridcell'], [role='columnheader'], [role='rowheader']")].filter((cell) => cell.getClientRects().length > 0);
|
|
829
989
|
element.setAttribute("role", "grid");
|
|
830
990
|
function focusCell(cell) { cells().forEach((item) => { item.tabIndex = item === cell ? 0 : -1; }); cell?.focus(); }
|
|
831
991
|
function keydown(event) {
|
|
992
|
+
if (event.target.matches("input,textarea,select,button")) return;
|
|
832
993
|
const cell = event.target.closest("[role='gridcell'], [role='columnheader'], [role='rowheader']");
|
|
833
994
|
if (!cell) return;
|
|
834
995
|
const row = cell.closest("[role='row']");
|
|
@@ -848,7 +1009,11 @@ function createDataGrid(element) {
|
|
|
848
1009
|
const first = cells()[0];
|
|
849
1010
|
cells().forEach((cell) => { cell.tabIndex = cell === first ? 0 : -1; });
|
|
850
1011
|
element.addEventListener("keydown", keydown);
|
|
851
|
-
return { focus: focusCell, destroy: () =>
|
|
1012
|
+
return { focus: focusCell, destroy: () => {
|
|
1013
|
+
disposed = true; request++; abort?.abort(); element.removeEventListener("keydown", keydown);
|
|
1014
|
+
if (scrollHandler) viewport.removeEventListener("scroll", scrollHandler);
|
|
1015
|
+
if (originalChildren) { element.replaceChildren(...originalChildren); element.setAttribute("role", "grid"); }
|
|
1016
|
+
}, refresh, setOptions, setRows, setPage, setSort, setFilter, select, getState, updateCell, load };
|
|
852
1017
|
}
|
|
853
1018
|
|
|
854
1019
|
function createTableSort(element) {
|
|
@@ -1905,7 +2070,7 @@ function createCoupon(element) {
|
|
|
1905
2070
|
}
|
|
1906
2071
|
|
|
1907
2072
|
function register(name, factory) {
|
|
1908
|
-
if (!name || typeof factory !== "function") throw new TypeError("
|
|
2073
|
+
if (!name || typeof factory !== "function") throw new TypeError("Gardenerim.register requires a name and factory function.");
|
|
1909
2074
|
registry.set(name, factory);
|
|
1910
2075
|
}
|
|
1911
2076
|
|
|
@@ -2098,7 +2263,7 @@ function init(root = document) {
|
|
|
2098
2263
|
if (root instanceof Element && root.matches(selector)) initElement(root, name);
|
|
2099
2264
|
root.querySelectorAll?.(selector).forEach((element) => initElement(element, name));
|
|
2100
2265
|
}
|
|
2101
|
-
return
|
|
2266
|
+
return Gardenerim;
|
|
2102
2267
|
}
|
|
2103
2268
|
|
|
2104
2269
|
function getInstance(elementOrSelector, name) {
|
|
@@ -2211,7 +2376,7 @@ function observe() {
|
|
|
2211
2376
|
observer.observe(document.documentElement, { childList: true, subtree: true, attributes: true });
|
|
2212
2377
|
}
|
|
2213
2378
|
|
|
2214
|
-
const
|
|
2379
|
+
const Gardenerim = Object.freeze({ version: "2.0.0", get behaviors() { return Object.freeze([...registry.keys()]); }, init, destroy, register, getInstance, emit, toast, observe });
|
|
2215
2380
|
|
|
2216
2381
|
if (typeof document !== "undefined") {
|
|
2217
2382
|
document.addEventListener("click", delegateClick);
|
|
@@ -2220,5 +2385,6 @@ if (typeof document !== "undefined") {
|
|
|
2220
2385
|
else queueMicrotask(start);
|
|
2221
2386
|
}
|
|
2222
2387
|
|
|
2223
|
-
|
|
2224
|
-
export
|
|
2388
|
+
|
|
2389
|
+
export { Gardenerim, init, destroy, register, getInstance, emit, toast, observe };
|
|
2390
|
+
export default Gardenerim;
|