gg-wf-scripts 2.4.0 → 2.8.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/README.md +52 -0
- package/dist/action-engine.d.ts +3 -0
- package/dist/action-engine.js +78 -0
- package/dist/action-engine.js.map +1 -0
- package/dist/actions.d.ts +14 -0
- package/dist/actions.js +12 -0
- package/dist/actions.js.map +1 -0
- package/dist/auth.d.ts +6 -0
- package/dist/auth.js +27 -0
- package/dist/auth.js.map +1 -0
- package/dist/bridges.d.ts +1 -0
- package/dist/bridges.js +33 -0
- package/dist/bridges.js.map +1 -0
- package/dist/data-engine.d.ts +3 -0
- package/dist/data-engine.js +158 -0
- package/dist/data-engine.js.map +1 -0
- package/dist/dialog.d.ts +1 -0
- package/dist/dialog.js +89 -0
- package/dist/dialog.js.map +1 -0
- package/dist/form-action-engine.d.ts +3 -0
- package/dist/form-action-engine.js +156 -0
- package/dist/form-action-engine.js.map +1 -0
- package/dist/form-actions.d.ts +22 -0
- package/dist/form-actions.js +15 -0
- package/dist/form-actions.js.map +1 -0
- package/dist/form-visibility.d.ts +1 -0
- package/dist/form-visibility.js +108 -0
- package/dist/form-visibility.js.map +1 -0
- package/dist/helpers/dom.d.ts +16 -0
- package/dist/helpers/dom.js +39 -0
- package/dist/helpers/dom.js.map +1 -0
- package/dist/helpers/path.d.ts +2 -0
- package/dist/helpers/path.js +9 -0
- package/dist/helpers/path.js.map +1 -0
- package/dist/helpers/run-handler.d.ts +22 -0
- package/dist/helpers/run-handler.js +33 -0
- package/dist/helpers/run-handler.js.map +1 -0
- package/dist/helpers/run-with-loading.d.ts +6 -0
- package/dist/helpers/run-with-loading.js +28 -0
- package/dist/helpers/run-with-loading.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/queries.d.ts +10 -0
- package/dist/queries.js +12 -0
- package/dist/queries.js.map +1 -0
- package/dist/query-params.d.ts +19 -0
- package/dist/query-params.js +142 -0
- package/dist/query-params.js.map +1 -0
- package/dist/switch-engine.d.ts +1 -0
- package/dist/switch-engine.js +21 -0
- package/dist/switch-engine.js.map +1 -0
- package/package.json +20 -2
- package/src/action-engine.js +0 -64
- package/src/actions.js +0 -14
- package/src/auth.js +0 -28
- package/src/bridges.js +0 -31
- package/src/data-engine.js +0 -145
- package/src/dialog.js +0 -86
- package/src/form-action-engine.js +0 -149
- package/src/form-actions.js +0 -21
- package/src/form-visibility.js +0 -122
- package/src/helpers/dom.js +0 -35
- package/src/helpers/log.js +0 -34
- package/src/helpers/path.js +0 -4
- package/src/index.js +0 -60
- package/src/queries.js +0 -14
- package/src/query-params.js +0 -144
- package/src/switch-engine.js +0 -22
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
type QueryChangeCallback = (key: string, value: string | null) => void;
|
|
2
|
+
/**
|
|
3
|
+
* Snapshot of the current URL query string as a URLSearchParams instance.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getParams(): URLSearchParams;
|
|
6
|
+
export declare function onQueryChanged(callback: QueryChangeCallback): () => void;
|
|
7
|
+
/**
|
|
8
|
+
* Set one or more URL query params and notify subscribers.
|
|
9
|
+
*/
|
|
10
|
+
export declare function setQueryParams(params: Array<{
|
|
11
|
+
key: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}>): void;
|
|
14
|
+
/**
|
|
15
|
+
* Remove one or more URL query params and notify subscribers.
|
|
16
|
+
*/
|
|
17
|
+
export declare function removeQueryParams(keys: string[]): void;
|
|
18
|
+
export declare function initQueryParams(): void;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const subscribers = [];
|
|
2
|
+
/**
|
|
3
|
+
* Snapshot of the current URL query string as a URLSearchParams instance.
|
|
4
|
+
*/
|
|
5
|
+
export function getParams() {
|
|
6
|
+
return new URL(window.location.href).searchParams;
|
|
7
|
+
}
|
|
8
|
+
export function onQueryChanged(callback) {
|
|
9
|
+
subscribers.push(callback);
|
|
10
|
+
return () => {
|
|
11
|
+
const idx = subscribers.indexOf(callback);
|
|
12
|
+
if (idx >= 0)
|
|
13
|
+
subscribers.splice(idx, 1);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function notify(key, value) {
|
|
17
|
+
subscribers.forEach((cb) => cb(key, value));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Set one or more URL query params and notify subscribers.
|
|
21
|
+
*/
|
|
22
|
+
export function setQueryParams(params) {
|
|
23
|
+
const url = new URL(window.location.href);
|
|
24
|
+
params.forEach(({ key, value }) => url.searchParams.set(key, value));
|
|
25
|
+
history.pushState({}, "", url);
|
|
26
|
+
params.forEach(({ key, value }) => notify(key, value));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Remove one or more URL query params and notify subscribers.
|
|
30
|
+
*/
|
|
31
|
+
export function removeQueryParams(keys) {
|
|
32
|
+
const url = new URL(window.location.href);
|
|
33
|
+
keys.forEach((key) => url.searchParams.delete(key));
|
|
34
|
+
history.pushState({}, "", url);
|
|
35
|
+
keys.forEach((key) => notify(key, null));
|
|
36
|
+
}
|
|
37
|
+
// ---- click delegation for gg-query-set / gg-query-remove ----
|
|
38
|
+
function handleQueryClick(target) {
|
|
39
|
+
if (!target)
|
|
40
|
+
return;
|
|
41
|
+
const setTrigger = target.closest("[gg-query-set]");
|
|
42
|
+
if (setTrigger) {
|
|
43
|
+
const attr = setTrigger.getAttribute("gg-query-set") ?? "";
|
|
44
|
+
const params = attr
|
|
45
|
+
.split(",")
|
|
46
|
+
.filter(Boolean)
|
|
47
|
+
.map((pair) => {
|
|
48
|
+
const [key, value] = pair.split(":");
|
|
49
|
+
return { key: key?.trim() ?? "", value: value?.trim() ?? "" };
|
|
50
|
+
})
|
|
51
|
+
.filter((p) => p.key && p.value);
|
|
52
|
+
if (params.length)
|
|
53
|
+
setQueryParams(params);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const removeTrigger = target.closest("[gg-query-remove]");
|
|
57
|
+
if (removeTrigger) {
|
|
58
|
+
const attr = removeTrigger.getAttribute("gg-query-remove") ?? "";
|
|
59
|
+
const keys = attr
|
|
60
|
+
.split(",")
|
|
61
|
+
.map((k) => k.trim())
|
|
62
|
+
.filter(Boolean);
|
|
63
|
+
if (keys.length)
|
|
64
|
+
removeQueryParams(keys);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function initQueryParams() {
|
|
69
|
+
document.addEventListener("click", (e) => {
|
|
70
|
+
handleQueryClick(e.target instanceof Element ? e.target : null);
|
|
71
|
+
});
|
|
72
|
+
// Shadow-root click forwarder — shadow DOM swallows bubbling, so anything
|
|
73
|
+
// inside a shadow tree dispatches `gg:shadow:click` with the real target.
|
|
74
|
+
document.addEventListener("gg:shadow:click", (e) => {
|
|
75
|
+
const detail = e.detail;
|
|
76
|
+
handleQueryClick(detail?.target ?? null);
|
|
77
|
+
});
|
|
78
|
+
initQueryBindings();
|
|
79
|
+
}
|
|
80
|
+
function syncBindInputFromUrl(el) {
|
|
81
|
+
const key = el.getAttribute("gg-query-bind");
|
|
82
|
+
if (!key)
|
|
83
|
+
return;
|
|
84
|
+
const value = new URL(window.location.href).searchParams.get(key) ?? "";
|
|
85
|
+
if (el.value !== value)
|
|
86
|
+
el.value = value;
|
|
87
|
+
}
|
|
88
|
+
function setupQueryBindInput(el) {
|
|
89
|
+
const key = el.getAttribute("gg-query-bind");
|
|
90
|
+
if (!key)
|
|
91
|
+
return;
|
|
92
|
+
const debounceMs = parseInt(el.getAttribute("gg-query-debounce") ?? "0", 10) || 0;
|
|
93
|
+
syncBindInputFromUrl(el);
|
|
94
|
+
let timer;
|
|
95
|
+
let suppress = false;
|
|
96
|
+
el.addEventListener("input", () => {
|
|
97
|
+
if (suppress)
|
|
98
|
+
return;
|
|
99
|
+
if (timer !== undefined)
|
|
100
|
+
clearTimeout(timer);
|
|
101
|
+
const fire = () => {
|
|
102
|
+
const value = el.value;
|
|
103
|
+
if (value === "") {
|
|
104
|
+
removeQueryParams([key]);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
setQueryParams([{ key, value }]);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
if (debounceMs > 0) {
|
|
111
|
+
timer = setTimeout(fire, debounceMs);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
fire();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
// When the URL changes from elsewhere (back button, programmatic), mirror
|
|
118
|
+
// it into the input without re-firing the input listener.
|
|
119
|
+
onQueryChanged((changedKey, value) => {
|
|
120
|
+
if (changedKey !== key)
|
|
121
|
+
return;
|
|
122
|
+
const next = value ?? "";
|
|
123
|
+
if (el.value === next)
|
|
124
|
+
return;
|
|
125
|
+
suppress = true;
|
|
126
|
+
el.value = next;
|
|
127
|
+
suppress = false;
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
function initQueryBindings() {
|
|
131
|
+
document
|
|
132
|
+
.querySelectorAll("[gg-query-bind]")
|
|
133
|
+
.forEach(setupQueryBindInput);
|
|
134
|
+
// Back/forward navigation doesn't fire pushState notifications, so
|
|
135
|
+
// re-sync all bound inputs from the URL on popstate.
|
|
136
|
+
window.addEventListener("popstate", () => {
|
|
137
|
+
document
|
|
138
|
+
.querySelectorAll("[gg-query-bind]")
|
|
139
|
+
.forEach(syncBindInputFromUrl);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=query-params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-params.js","sourceRoot":"","sources":["../src/query-params.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function initSwitchEngine(): void;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { applySwitchState } from "./helpers/dom.js";
|
|
2
|
+
export function initSwitchEngine() {
|
|
3
|
+
// Re-apply whenever gg-switch-state changes on any element.
|
|
4
|
+
new MutationObserver((mutations) => {
|
|
5
|
+
mutations.forEach((m) => {
|
|
6
|
+
if (m.attributeName === "gg-switch-state" && m.target instanceof Element) {
|
|
7
|
+
applySwitchState(m.target);
|
|
8
|
+
}
|
|
9
|
+
});
|
|
10
|
+
}).observe(document.body, {
|
|
11
|
+
attributes: true,
|
|
12
|
+
attributeFilter: ["gg-switch-state"],
|
|
13
|
+
subtree: true,
|
|
14
|
+
});
|
|
15
|
+
// Apply initial state for any elements that already have gg-switch-state
|
|
16
|
+
// set at load time, so we don't flash all children before the first mutation.
|
|
17
|
+
document
|
|
18
|
+
.querySelectorAll("[gg-switch-state]")
|
|
19
|
+
.forEach(applySwitchState);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=switch-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch-engine.js","sourceRoot":"","sources":["../src/switch-engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,UAAU,gBAAgB;IAC9B,4DAA4D;IAC5D,IAAI,gBAAgB,CAAC,CAAC,SAAS,EAAE,EAAE;QACjC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;YACtB,IAAI,CAAC,CAAC,aAAa,KAAK,iBAAiB,IAAI,CAAC,CAAC,MAAM,YAAY,OAAO,EAAE,CAAC;gBACzE,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE;QACxB,UAAU,EAAE,IAAI;QAChB,eAAe,EAAE,CAAC,iBAAiB,CAAC;QACpC,OAAO,EAAE,IAAI;KACd,CAAC,CAAC;IAEH,yEAAyE;IACzE,8EAA8E;IAC9E,QAAQ;SACL,gBAAgB,CAAC,mBAAmB,CAAC;SACrC,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC/B,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gg-wf-scripts",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.8.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"exports":
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"default": "./dist/index.js"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"clean": "rimraf dist",
|
|
16
|
+
"build": "npm run clean && tsc",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"prepublishOnly": "npm run build"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"rimraf": "^6.1.3",
|
|
22
|
+
"typescript": "^6.0.3"
|
|
23
|
+
}
|
|
6
24
|
}
|
package/src/action-engine.js
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { actionRegistry } from "./actions.js";
|
|
2
|
-
import { withDebugLog } from "./helpers/log.js";
|
|
3
|
-
import { getParams } from "./query-params.js";
|
|
4
|
-
|
|
5
|
-
function parseActionData(el) {
|
|
6
|
-
const attr = el.getAttribute("gg-action-data");
|
|
7
|
-
if (!attr) return {};
|
|
8
|
-
const data = {};
|
|
9
|
-
attr
|
|
10
|
-
.split(",")
|
|
11
|
-
.filter(Boolean)
|
|
12
|
-
.forEach((pair) => {
|
|
13
|
-
const [key, value] = pair.split(":");
|
|
14
|
-
if (key?.trim()) data[key.trim()] = value?.trim() ?? "";
|
|
15
|
-
});
|
|
16
|
-
return data;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function findRecord(el) {
|
|
20
|
-
let node = el.parentElement;
|
|
21
|
-
while (node) {
|
|
22
|
-
if (node.__ggRecord) return node.__ggRecord;
|
|
23
|
-
node = node.parentElement;
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export function initActionEngine(context, { debug = false } = {}) {
|
|
29
|
-
async function handleAction(el) {
|
|
30
|
-
const id = el.getAttribute("gg-action");
|
|
31
|
-
const action = actionRegistry[id];
|
|
32
|
-
if (!action) {
|
|
33
|
-
console.warn(`[gg-action] no action registered for "${id}"`);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const record = findRecord(el);
|
|
38
|
-
const explicit = parseActionData(el);
|
|
39
|
-
const data = record ? { ...record, ...explicit } : explicit;
|
|
40
|
-
const params = getParams();
|
|
41
|
-
|
|
42
|
-
const result = await withDebugLog(
|
|
43
|
-
"[gg-action]",
|
|
44
|
-
id,
|
|
45
|
-
{ trigger: el, data, params: Object.fromEntries(params) },
|
|
46
|
-
debug,
|
|
47
|
-
() => action(context, data, params),
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
if (result?.ok === false) {
|
|
51
|
-
console.warn(`[gg-action] "${id}" failed:`, result.error ?? "unknown error");
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
document.addEventListener("click", (e) => {
|
|
56
|
-
const trigger = e.target.closest("[gg-action]");
|
|
57
|
-
if (trigger) handleAction(trigger);
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
document.addEventListener("gg:shadow:click", (e) => {
|
|
61
|
-
const trigger = e.detail.target.closest("[gg-action]");
|
|
62
|
-
if (trigger) handleAction(trigger);
|
|
63
|
-
});
|
|
64
|
-
}
|
package/src/actions.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export const actionRegistry = {};
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Register an action triggered by gg-action="<id>" on click.
|
|
5
|
-
*
|
|
6
|
-
* @param {string} id - The action identifier, referenced by gg-action="<id>" in markup.
|
|
7
|
-
* @param {(context: object, data: object, params: URLSearchParams) => Promise<{ok: boolean, error?: any}>} fn
|
|
8
|
-
* Receives the context object passed to init(), a data object (merged from the nearest
|
|
9
|
-
* gg-data record and any explicit gg-action-data attribute), and a URLSearchParams snapshot
|
|
10
|
-
* of the current URL query string. Return { ok: true } or { ok: false, error }.
|
|
11
|
-
*/
|
|
12
|
-
export function registerAction(id, fn) {
|
|
13
|
-
actionRegistry[id] = fn;
|
|
14
|
-
}
|
package/src/auth.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
export async function initAuth(context, auth) {
|
|
2
|
-
const { getUser, onChange, roleQuery } = auth;
|
|
3
|
-
|
|
4
|
-
async function applyAuthAttrs(userId) {
|
|
5
|
-
const body = document.body;
|
|
6
|
-
if (!userId) {
|
|
7
|
-
body.setAttribute("gg-auth", "false");
|
|
8
|
-
body.removeAttribute("gg-role");
|
|
9
|
-
return;
|
|
10
|
-
}
|
|
11
|
-
body.setAttribute("gg-auth", "true");
|
|
12
|
-
if (roleQuery) {
|
|
13
|
-
const role = await roleQuery(context, userId);
|
|
14
|
-
if (role) {
|
|
15
|
-
body.setAttribute("gg-role", role);
|
|
16
|
-
} else {
|
|
17
|
-
body.removeAttribute("gg-role");
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const userId = await getUser();
|
|
23
|
-
applyAuthAttrs(userId ?? null);
|
|
24
|
-
|
|
25
|
-
if (onChange) {
|
|
26
|
-
onChange((userId) => applyAuthAttrs(userId ?? null));
|
|
27
|
-
}
|
|
28
|
-
}
|
package/src/bridges.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { setSwitchState } from "./helpers/dom.js";
|
|
2
|
-
import { onQueryChanged } from "./query-params.js";
|
|
3
|
-
|
|
4
|
-
export function initBridges() {
|
|
5
|
-
// ---- gg-switch-query: URL params → gg-switch-state ----
|
|
6
|
-
// On any URL param change, mirror its value onto matching
|
|
7
|
-
// [gg-switch-query="<key>"] elements' gg-switch-state.
|
|
8
|
-
onQueryChanged((key, value) => {
|
|
9
|
-
document
|
|
10
|
-
.querySelectorAll(`[gg-switch-query="${CSS.escape(key)}"]`)
|
|
11
|
-
.forEach((el) => setSwitchState(el, value));
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
// Initial-load pass: read current URL params and set state for every
|
|
15
|
-
// [gg-switch-query] on the page, so we don't flash before the first change.
|
|
16
|
-
const params = new URLSearchParams(window.location.search);
|
|
17
|
-
document.querySelectorAll("[gg-switch-query]").forEach((el) => {
|
|
18
|
-
const key = el.getAttribute("gg-switch-query");
|
|
19
|
-
setSwitchState(el, params.get(key));
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
// ---- webflow:emit → Webflow IX ----
|
|
23
|
-
window.addEventListener("load", () => {
|
|
24
|
-
Webflow.push(() => {
|
|
25
|
-
const wfIx = Webflow.require("ix3");
|
|
26
|
-
document.addEventListener("webflow:emit", (e) => {
|
|
27
|
-
wfIx.emit(e.detail.event);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
});
|
|
31
|
-
}
|
package/src/data-engine.js
DELETED
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { getPath } from "./helpers/path.js";
|
|
2
|
-
import {
|
|
3
|
-
populateFields,
|
|
4
|
-
setSwitchState,
|
|
5
|
-
applySwitchState,
|
|
6
|
-
} from "./helpers/dom.js";
|
|
7
|
-
import { withDebugLog } from "./helpers/log.js";
|
|
8
|
-
import { queryRegistry } from "./queries.js";
|
|
9
|
-
import { onQueryChanged, getParams } from "./query-params.js";
|
|
10
|
-
|
|
11
|
-
function applySwitchFields(root, record) {
|
|
12
|
-
root.querySelectorAll("[gg-switch-field]").forEach((el) => {
|
|
13
|
-
const path = el.getAttribute("gg-switch-field");
|
|
14
|
-
const value = getPath(record, path);
|
|
15
|
-
setSwitchState(el, value);
|
|
16
|
-
applySwitchState(el);
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function populateFormFields(root, record) {
|
|
21
|
-
root.querySelectorAll(
|
|
22
|
-
"input[name], select[name], textarea[name]",
|
|
23
|
-
).forEach((el) => {
|
|
24
|
-
const name = el.getAttribute("name");
|
|
25
|
-
const value = getPath(record, name);
|
|
26
|
-
if (value == null) return;
|
|
27
|
-
|
|
28
|
-
if (el instanceof HTMLInputElement) {
|
|
29
|
-
if (el.type === "checkbox") {
|
|
30
|
-
el.checked = Boolean(value);
|
|
31
|
-
} else if (el.type === "radio") {
|
|
32
|
-
el.checked = String(el.value) === String(value);
|
|
33
|
-
} else {
|
|
34
|
-
el.value = String(value);
|
|
35
|
-
}
|
|
36
|
-
} else {
|
|
37
|
-
el.value = String(value);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
41
|
-
el.dispatchEvent(new Event("change", { bubbles: true }));
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export function initDataEngine(context, { debug = false } = {}) {
|
|
46
|
-
async function runQuery(container) {
|
|
47
|
-
const isList = container.hasAttribute("gg-data-list");
|
|
48
|
-
const isForm = container.hasAttribute("gg-data-form");
|
|
49
|
-
const id = container.getAttribute(
|
|
50
|
-
isList ? "gg-data-list" : isForm ? "gg-data-form" : "gg-data",
|
|
51
|
-
);
|
|
52
|
-
const query = queryRegistry[id];
|
|
53
|
-
if (!query) {
|
|
54
|
-
console.warn(`[gg-data] no query registered for "${id}"`);
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const params = getParams();
|
|
59
|
-
const result = await withDebugLog(
|
|
60
|
-
"[gg-data]",
|
|
61
|
-
id,
|
|
62
|
-
{ container, params: Object.fromEntries(params) },
|
|
63
|
-
debug,
|
|
64
|
-
() => query(context, params),
|
|
65
|
-
);
|
|
66
|
-
if (result === undefined) return;
|
|
67
|
-
|
|
68
|
-
if (isList) {
|
|
69
|
-
if (!Array.isArray(result)) {
|
|
70
|
-
console.warn(
|
|
71
|
-
`[gg-data-list] query "${id}" did not return an array`,
|
|
72
|
-
);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const template = container.querySelector("[gg-list-template]");
|
|
77
|
-
if (!template) {
|
|
78
|
-
console.warn(
|
|
79
|
-
`[gg-data-list] no [gg-list-template] inside "${id}"`,
|
|
80
|
-
);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
Array.from(container.children).forEach((child) => {
|
|
85
|
-
if (child !== template) child.remove();
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
result.forEach((record) => {
|
|
89
|
-
const clone = template.cloneNode(true);
|
|
90
|
-
clone.removeAttribute("gg-list-template");
|
|
91
|
-
clone.setAttribute(
|
|
92
|
-
"gg-query-set",
|
|
93
|
-
`modal:view,id:${record.id}`,
|
|
94
|
-
);
|
|
95
|
-
clone.style.display = "flex";
|
|
96
|
-
if (record?.id != null) clone.id = String(record.id);
|
|
97
|
-
clone.__ggRecord = record;
|
|
98
|
-
populateFields(clone, record);
|
|
99
|
-
applySwitchFields(clone, record);
|
|
100
|
-
container.appendChild(clone);
|
|
101
|
-
});
|
|
102
|
-
} else if (isForm) {
|
|
103
|
-
if (Array.isArray(result)) {
|
|
104
|
-
console.warn(
|
|
105
|
-
`[gg-data-form] query "${id}" returned an array; expected a single record`,
|
|
106
|
-
);
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
if (!result) return;
|
|
110
|
-
container.__ggRecord = result;
|
|
111
|
-
populateFormFields(container, result);
|
|
112
|
-
} else {
|
|
113
|
-
if (Array.isArray(result)) {
|
|
114
|
-
console.warn(
|
|
115
|
-
`[gg-data] query "${id}" returned an array; use gg-data-list instead`,
|
|
116
|
-
);
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if (!result) return;
|
|
120
|
-
container.__ggRecord = result;
|
|
121
|
-
populateFields(container, result);
|
|
122
|
-
applySwitchFields(container, result);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Run all data containers on load
|
|
127
|
-
document
|
|
128
|
-
.querySelectorAll("[gg-data], [gg-data-list], [gg-data-form]")
|
|
129
|
-
.forEach(runQuery);
|
|
130
|
-
|
|
131
|
-
// Re-run queries when matching URL params change
|
|
132
|
-
onQueryChanged((key) => {
|
|
133
|
-
document
|
|
134
|
-
.querySelectorAll(
|
|
135
|
-
"[gg-data][gg-data-on], [gg-data-list][gg-data-on], [gg-data-form][gg-data-on]",
|
|
136
|
-
)
|
|
137
|
-
.forEach((c) => {
|
|
138
|
-
const keys = c
|
|
139
|
-
.getAttribute("gg-data-on")
|
|
140
|
-
.split(",")
|
|
141
|
-
.map((s) => s.trim());
|
|
142
|
-
if (keys.includes(key)) runQuery(c);
|
|
143
|
-
});
|
|
144
|
-
});
|
|
145
|
-
}
|
package/src/dialog.js
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { removeQueryParams, onQueryChanged } from "./query-params.js";
|
|
2
|
-
|
|
3
|
-
function stopLenis() {
|
|
4
|
-
if (typeof lenis !== "undefined") lenis.stop();
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
function startLenis() {
|
|
8
|
-
if (typeof lenis !== "undefined") lenis.start();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function openDialog() {
|
|
12
|
-
const dialog = document.querySelector("dialog");
|
|
13
|
-
if (!dialog) return;
|
|
14
|
-
dialog.removeAttribute("aria-hidden");
|
|
15
|
-
dialog.removeAttribute("inert");
|
|
16
|
-
dialog.showModal();
|
|
17
|
-
stopLenis();
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function closeDialog() {
|
|
21
|
-
const dialog = document.querySelector("dialog");
|
|
22
|
-
if (!dialog) return;
|
|
23
|
-
dialog.setAttribute("aria-hidden", "true");
|
|
24
|
-
dialog.setAttribute("inert", "");
|
|
25
|
-
dialog.close();
|
|
26
|
-
startLenis();
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function dismissViaUrlOrDirect() {
|
|
30
|
-
const modalParam = new URLSearchParams(window.location.search).get("modal");
|
|
31
|
-
if (modalParam) {
|
|
32
|
-
removeQueryParams(["modal", "id"]);
|
|
33
|
-
} else {
|
|
34
|
-
closeDialog();
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function syncDialogToUrl() {
|
|
39
|
-
const modalParam = new URLSearchParams(window.location.search).get("modal");
|
|
40
|
-
if (modalParam) {
|
|
41
|
-
openDialog();
|
|
42
|
-
} else {
|
|
43
|
-
closeDialog();
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function initDialog() {
|
|
48
|
-
// Subscribe to query param changes — open/close when "modal" changes
|
|
49
|
-
onQueryChanged((key, value) => {
|
|
50
|
-
if (key !== "modal") return;
|
|
51
|
-
if (value) {
|
|
52
|
-
openDialog();
|
|
53
|
-
} else {
|
|
54
|
-
closeDialog();
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// Inbound events from external code
|
|
59
|
-
document.addEventListener("gg:dialog:open", openDialog);
|
|
60
|
-
document.addEventListener("gg:dialog:close", closeDialog);
|
|
61
|
-
|
|
62
|
-
// Backdrop click
|
|
63
|
-
document.addEventListener("click", (e) => {
|
|
64
|
-
if (!e.target.matches("dialog[open]")) return;
|
|
65
|
-
const rect = e.target.getBoundingClientRect();
|
|
66
|
-
const outside =
|
|
67
|
-
e.clientX < rect.left ||
|
|
68
|
-
e.clientX > rect.right ||
|
|
69
|
-
e.clientY < rect.top ||
|
|
70
|
-
e.clientY > rect.bottom;
|
|
71
|
-
if (outside) dismissViaUrlOrDirect();
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// Escape key — preempt the default close so the URL stays source of truth
|
|
75
|
-
document.addEventListener("cancel", (e) => {
|
|
76
|
-
if (!e.target.matches("dialog")) return;
|
|
77
|
-
e.preventDefault();
|
|
78
|
-
dismissViaUrlOrDirect();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
// Back button
|
|
82
|
-
window.addEventListener("popstate", syncDialogToUrl);
|
|
83
|
-
|
|
84
|
-
// Initial load
|
|
85
|
-
syncDialogToUrl();
|
|
86
|
-
}
|