gg-wf-scripts 2.5.0 → 3.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.
Files changed (84) hide show
  1. package/README.md +33 -0
  2. package/dist/action-engine.d.ts +2 -0
  3. package/dist/action-engine.js +97 -0
  4. package/dist/action-engine.js.map +1 -0
  5. package/dist/actions.d.ts +5 -0
  6. package/dist/actions.js +2 -0
  7. package/dist/actions.js.map +1 -0
  8. package/dist/attrs.d.ts +59 -0
  9. package/dist/attrs.js +67 -0
  10. package/dist/attrs.js.map +1 -0
  11. package/dist/auth.d.ts +6 -0
  12. package/dist/auth.js +28 -0
  13. package/dist/auth.js.map +1 -0
  14. package/dist/bridges.d.ts +1 -0
  15. package/dist/bridges.js +43 -0
  16. package/dist/bridges.js.map +1 -0
  17. package/dist/data-engine.d.ts +2 -0
  18. package/dist/data-engine.js +153 -0
  19. package/dist/data-engine.js.map +1 -0
  20. package/dist/dialog.d.ts +1 -0
  21. package/dist/dialog.js +93 -0
  22. package/dist/dialog.js.map +1 -0
  23. package/dist/dom-observer.d.ts +4 -0
  24. package/dist/dom-observer.js +47 -0
  25. package/dist/dom-observer.js.map +1 -0
  26. package/dist/engine-deps.d.ts +23 -0
  27. package/dist/engine-deps.js +2 -0
  28. package/dist/engine-deps.js.map +1 -0
  29. package/dist/errors.d.ts +25 -0
  30. package/dist/errors.js +30 -0
  31. package/dist/errors.js.map +1 -0
  32. package/dist/form-action-engine.d.ts +2 -0
  33. package/dist/form-action-engine.js +173 -0
  34. package/dist/form-action-engine.js.map +1 -0
  35. package/dist/form-actions.d.ts +10 -0
  36. package/dist/form-actions.js +2 -0
  37. package/dist/form-actions.js.map +1 -0
  38. package/dist/form-visibility.d.ts +1 -0
  39. package/dist/form-visibility.js +109 -0
  40. package/dist/form-visibility.js.map +1 -0
  41. package/dist/helpers/dom.d.ts +16 -0
  42. package/dist/helpers/dom.js +39 -0
  43. package/dist/helpers/dom.js.map +1 -0
  44. package/dist/helpers/form-field.d.ts +19 -0
  45. package/dist/helpers/form-field.js +58 -0
  46. package/dist/helpers/form-field.js.map +1 -0
  47. package/dist/helpers/path.d.ts +2 -0
  48. package/dist/helpers/path.js +9 -0
  49. package/dist/helpers/path.js.map +1 -0
  50. package/dist/helpers/run-handler.d.ts +26 -0
  51. package/dist/helpers/run-handler.js +36 -0
  52. package/dist/helpers/run-handler.js.map +1 -0
  53. package/dist/helpers/run-with-loading.d.ts +6 -0
  54. package/dist/helpers/run-with-loading.js +28 -0
  55. package/dist/helpers/run-with-loading.js.map +1 -0
  56. package/dist/index.d.ts +69 -0
  57. package/dist/index.js +72 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/queries.d.ts +1 -0
  60. package/dist/queries.js +2 -0
  61. package/dist/queries.js.map +1 -0
  62. package/dist/query-params.d.ts +19 -0
  63. package/dist/query-params.js +160 -0
  64. package/dist/query-params.js.map +1 -0
  65. package/dist/switch-engine.d.ts +1 -0
  66. package/dist/switch-engine.js +28 -0
  67. package/dist/switch-engine.js.map +1 -0
  68. package/package.json +25 -2
  69. package/src/action-engine.js +0 -64
  70. package/src/actions.js +0 -14
  71. package/src/auth.js +0 -28
  72. package/src/bridges.js +0 -31
  73. package/src/data-engine.js +0 -165
  74. package/src/dialog.js +0 -86
  75. package/src/form-action-engine.js +0 -149
  76. package/src/form-actions.js +0 -21
  77. package/src/form-visibility.js +0 -122
  78. package/src/helpers/dom.js +0 -35
  79. package/src/helpers/log.js +0 -34
  80. package/src/helpers/path.js +0 -4
  81. package/src/index.js +0 -60
  82. package/src/queries.js +0 -14
  83. package/src/query-params.js +0 -144
  84. package/src/switch-engine.js +0 -22
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dialog.js","sourceRoot":"","sources":["../src/dialog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ type ElementHandler = (el: Element) => void;
2
+ export declare function onElement(selector: string, handler: ElementHandler): () => void;
3
+ export declare function startDomObserver(): () => void;
4
+ export {};
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Shared MutationObserver. Engines call `onElement(selector, handler)` to be
3
+ * notified when a matching element is present at start time **or** later
4
+ * inserted into the DOM (Webflow IX, CMS templates, custom elements). One
5
+ * observer for the whole library — not one per engine.
6
+ *
7
+ * `start()` returns the global teardown; `onElement()` returns a per-handler
8
+ * teardown so engines can clean up their own subscriptions in dispose().
9
+ */
10
+ const subscriptions = [];
11
+ let observer = null;
12
+ export function onElement(selector, handler) {
13
+ const sub = { selector, handler };
14
+ subscriptions.push(sub);
15
+ document.querySelectorAll(selector).forEach(handler);
16
+ return () => {
17
+ const idx = subscriptions.indexOf(sub);
18
+ if (idx >= 0)
19
+ subscriptions.splice(idx, 1);
20
+ };
21
+ }
22
+ export function startDomObserver() {
23
+ if (observer)
24
+ return () => { };
25
+ observer = new MutationObserver((mutations) => {
26
+ for (const m of mutations) {
27
+ m.addedNodes.forEach((node) => {
28
+ if (!(node instanceof Element))
29
+ return;
30
+ for (const sub of subscriptions) {
31
+ if (node.matches(sub.selector))
32
+ sub.handler(node);
33
+ node
34
+ .querySelectorAll(sub.selector)
35
+ .forEach((el) => sub.handler(el));
36
+ }
37
+ });
38
+ }
39
+ });
40
+ observer.observe(document.body, { childList: true, subtree: true });
41
+ return () => {
42
+ observer?.disconnect();
43
+ observer = null;
44
+ subscriptions.length = 0;
45
+ };
46
+ }
47
+ //# sourceMappingURL=dom-observer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-observer.js","sourceRoot":"","sources":["../src/dom-observer.ts"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AAEH,MAAM,aAAa,GAAmB,EAAE,CAAC;AACzC,IAAI,QAAQ,GAA4B,IAAI,CAAC;AAE7C,MAAM,UAAU,SAAS,CACvB,QAAgB,EAChB,OAAuB;IAEvB,MAAM,GAAG,GAAiB,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAChD,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD,OAAO,GAAG,EAAE;QACV,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACvC,IAAI,GAAG,IAAI,CAAC;YAAE,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,QAAQ;QAAE,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAC9B,QAAQ,GAAG,IAAI,gBAAgB,CAAC,CAAC,SAAS,EAAE,EAAE;QAC5C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;YAC1B,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC5B,IAAI,CAAC,CAAC,IAAI,YAAY,OAAO,CAAC;oBAAE,OAAO;gBACvC,KAAK,MAAM,GAAG,IAAI,aAAa,EAAE,CAAC;oBAChC,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;wBAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;oBAClD,IAAI;yBACD,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC;yBAC9B,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;gBACtC,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACpE,OAAO,GAAG,EAAE;QACV,QAAQ,EAAE,UAAU,EAAE,CAAC;QACvB,QAAQ,GAAG,IAAI,CAAC;QAChB,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { GgErrorEvent } from "./errors.js";
2
+ import type { Query } from "./queries.js";
3
+ import type { Action } from "./actions.js";
4
+ import type { FormAction } from "./form-actions.js";
5
+ /**
6
+ * The minimum surface every engine needs. Engines should depend on this (or a
7
+ * superset) instead of the full `App<TContext>` so they're easier to test and
8
+ * the dependency graph stays explicit.
9
+ */
10
+ export type EngineCore<TContext> = {
11
+ context: TContext;
12
+ debug: boolean;
13
+ emitError: (event: GgErrorEvent) => void;
14
+ };
15
+ export type DataEngineDeps<TContext> = EngineCore<TContext> & {
16
+ queries: Record<string, Query<TContext>>;
17
+ };
18
+ export type ActionEngineDeps<TContext> = EngineCore<TContext> & {
19
+ actions: Record<string, Action<TContext>>;
20
+ };
21
+ export type FormActionEngineDeps<TContext> = EngineCore<TContext> & {
22
+ formActions: Record<string, FormAction<TContext>>;
23
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=engine-deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine-deps.js","sourceRoot":"","sources":["../src/engine-deps.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Emitted whenever a registered query, action, or form action throws — and
3
+ * for non-throwing failure modes the engines detect (missing handler, wrong
4
+ * return shape). Subscribe via `app.onError(handler)` to forward to Sentry,
5
+ * Datadog, or any other error tracker.
6
+ */
7
+ export type GgErrorEvent = {
8
+ /** Engine label, e.g. "[gg-action]", "[gg-data]", "[gg-form-action]". */
9
+ prefix: string;
10
+ /** Handler id (the value of the gg-action / gg-data / gg-form-action attr). */
11
+ id: string;
12
+ /** The thrown error or a string describing the non-throw failure. */
13
+ error: unknown;
14
+ /** Engine-specific context: trigger element, form, params, etc. */
15
+ fields?: Record<string, unknown>;
16
+ };
17
+ export type ErrorHandler = (event: GgErrorEvent) => void;
18
+ /**
19
+ * Internal helper that owns the subscriber list. Lives on the App instance.
20
+ */
21
+ export declare function createErrorBus(): {
22
+ subscribe: (handler: ErrorHandler) => () => void;
23
+ emit: (event: GgErrorEvent) => void;
24
+ clear: () => void;
25
+ };
package/dist/errors.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Internal helper that owns the subscriber list. Lives on the App instance.
3
+ */
4
+ export function createErrorBus() {
5
+ const handlers = [];
6
+ return {
7
+ subscribe(handler) {
8
+ handlers.push(handler);
9
+ return () => {
10
+ const idx = handlers.indexOf(handler);
11
+ if (idx >= 0)
12
+ handlers.splice(idx, 1);
13
+ };
14
+ },
15
+ emit(event) {
16
+ handlers.forEach((h) => {
17
+ try {
18
+ h(event);
19
+ }
20
+ catch (err) {
21
+ console.error("[gg] onError handler threw:", err);
22
+ }
23
+ });
24
+ },
25
+ clear() {
26
+ handlers.length = 0;
27
+ },
28
+ };
29
+ }
30
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAmBA;;GAEG;AACH,MAAM,UAAU,cAAc;IAK5B,MAAM,QAAQ,GAAmB,EAAE,CAAC;IACpC,OAAO;QACL,SAAS,CAAC,OAAO;YACf,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACvB,OAAO,GAAG,EAAE;gBACV,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACtC,IAAI,GAAG,IAAI,CAAC;oBAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACxC,CAAC,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,KAAK;YACR,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;gBACrB,IAAI,CAAC;oBACH,CAAC,CAAC,KAAK,CAAC,CAAC;gBACX,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,GAAG,CAAC,CAAC;gBACpD,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QACD,KAAK;YACH,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { FormActionEngineDeps } from "./engine-deps.js";
2
+ export declare function initFormActionEngine<TContext>(deps: FormActionEngineDeps<TContext>): () => void;
@@ -0,0 +1,173 @@
1
+ import { ATTR, SEL } from "./attrs.js";
2
+ import { populateFields } from "./helpers/dom.js";
3
+ import { findInputs } from "./helpers/form-field.js";
4
+ import { runHandler } from "./helpers/run-handler.js";
5
+ import { runWithLoading } from "./helpers/run-with-loading.js";
6
+ import { onElement } from "./dom-observer.js";
7
+ import { getParams } from "./query-params.js";
8
+ function clearFieldError(form, name) {
9
+ findInputs(form, name).forEach((el) => {
10
+ el.removeAttribute(ATTR.formFieldInvalid);
11
+ });
12
+ const escaped = CSS.escape(name);
13
+ form
14
+ .querySelectorAll(`[${ATTR.formFieldError}="${escaped}"]`)
15
+ .forEach((el) => {
16
+ el.textContent = "";
17
+ });
18
+ }
19
+ function clearFormErrors(form) {
20
+ form.querySelectorAll(SEL.formFieldInvalid).forEach((el) => {
21
+ el.removeAttribute(ATTR.formFieldInvalid);
22
+ });
23
+ form.querySelectorAll(SEL.formFieldError).forEach((el) => {
24
+ el.textContent = "";
25
+ });
26
+ form.querySelectorAll(SEL.formError).forEach((el) => {
27
+ el.textContent = "";
28
+ });
29
+ form.querySelectorAll(SEL.formErrorList).forEach((list) => {
30
+ const template = list.querySelector(SEL.listTemplate);
31
+ Array.from(list.children).forEach((child) => {
32
+ if (child !== template)
33
+ child.remove();
34
+ });
35
+ });
36
+ }
37
+ function applyFieldErrors(form, fieldErrors) {
38
+ fieldErrors.forEach(({ name, message }) => {
39
+ if (!name)
40
+ return;
41
+ findInputs(form, name).forEach((el) => {
42
+ el.setAttribute(ATTR.formFieldInvalid, "true");
43
+ });
44
+ const escaped = CSS.escape(name);
45
+ form
46
+ .querySelectorAll(`[${ATTR.formFieldError}="${escaped}"]`)
47
+ .forEach((el) => {
48
+ el.textContent = message ?? "";
49
+ });
50
+ });
51
+ }
52
+ function applyErrorList(form, fieldErrors) {
53
+ form.querySelectorAll(SEL.formErrorList).forEach((list) => {
54
+ const template = list.querySelector(SEL.listTemplate);
55
+ if (!template) {
56
+ console.warn(`[${ATTR.formErrorList}] no [${ATTR.listTemplate}] inside list:`, list);
57
+ return;
58
+ }
59
+ fieldErrors.forEach((record) => {
60
+ const clone = template.cloneNode(true);
61
+ clone.removeAttribute(ATTR.listTemplate);
62
+ clone.style.display = "";
63
+ populateFields(clone, record);
64
+ list.appendChild(clone);
65
+ });
66
+ });
67
+ }
68
+ function applyFormError(form, error) {
69
+ if (error == null)
70
+ return;
71
+ const message = typeof error === "string" ? error : String(error);
72
+ form.querySelectorAll(SEL.formError).forEach((el) => {
73
+ el.textContent = message;
74
+ });
75
+ }
76
+ function bindFieldClearOnInput(form) {
77
+ if (form.__ggFormErrorBound)
78
+ return;
79
+ form.__ggFormErrorBound = true;
80
+ form.addEventListener("input", (e) => {
81
+ const target = e.target;
82
+ if (!(target instanceof Element))
83
+ return;
84
+ const name = target.getAttribute("name");
85
+ if (!name)
86
+ return;
87
+ if (target.hasAttribute(ATTR.formFieldInvalid)) {
88
+ clearFieldError(form, name);
89
+ }
90
+ });
91
+ }
92
+ async function handleSubmit(form, event, deps) {
93
+ const id = form.getAttribute(ATTR.formAction);
94
+ if (!id)
95
+ return;
96
+ const action = deps.formActions[id];
97
+ if (!action) {
98
+ console.warn(`[gg-form-action] no form action registered for "${id}"`);
99
+ deps.emitError({
100
+ prefix: "[gg-form-action]",
101
+ id,
102
+ error: "no form action registered",
103
+ fields: { form },
104
+ });
105
+ return;
106
+ }
107
+ event.preventDefault();
108
+ if (form.hasAttribute(ATTR.loading))
109
+ return;
110
+ if (form.hasAttribute(ATTR.confirm)) {
111
+ const text = form.getAttribute(ATTR.confirmText) || "Are you sure?";
112
+ if (!window.confirm(text))
113
+ return;
114
+ }
115
+ clearFormErrors(form);
116
+ const formData = new FormData(form);
117
+ const params = getParams();
118
+ const submitControls = form.querySelectorAll('button[type="submit"], button:not([type]), input[type="submit"]');
119
+ const handlerResult = await runWithLoading([form, ...submitControls], () => runHandler({
120
+ prefix: "[gg-form-action]",
121
+ id,
122
+ fields: {
123
+ form,
124
+ formData: Object.fromEntries(formData),
125
+ params: Object.fromEntries(params),
126
+ },
127
+ debug: deps.debug,
128
+ emitError: deps.emitError,
129
+ }, () => action(deps.context, formData, params)));
130
+ if (!handlerResult.ok) {
131
+ applyFormError(form, "Something went wrong. Please try again.");
132
+ return;
133
+ }
134
+ const result = handlerResult.value;
135
+ if (result && result.ok === false) {
136
+ const failure = result;
137
+ const fieldErrors = Array.isArray(failure.field_errors)
138
+ ? failure.field_errors
139
+ : [];
140
+ applyFieldErrors(form, fieldErrors);
141
+ applyErrorList(form, fieldErrors);
142
+ applyFormError(form, failure.error);
143
+ if (!fieldErrors.length && failure.error == null) {
144
+ console.warn(`[gg-form-action] "${id}" returned ok:false with no error or field_errors`);
145
+ }
146
+ deps.emitError({
147
+ prefix: "[gg-form-action]",
148
+ id,
149
+ error: failure.error ?? "validation",
150
+ fields: { form, fieldErrors },
151
+ });
152
+ }
153
+ }
154
+ export function initFormActionEngine(deps) {
155
+ const unbind = onElement(SEL.formAction, (el) => {
156
+ if (el instanceof HTMLFormElement)
157
+ bindFieldClearOnInput(el);
158
+ });
159
+ const onSubmit = (e) => {
160
+ const form = e.target;
161
+ if (form instanceof HTMLFormElement &&
162
+ form.hasAttribute(ATTR.formAction)) {
163
+ bindFieldClearOnInput(form);
164
+ handleSubmit(form, e, deps);
165
+ }
166
+ };
167
+ document.addEventListener("submit", onSubmit);
168
+ return () => {
169
+ unbind();
170
+ document.removeEventListener("submit", onSubmit);
171
+ };
172
+ }
173
+ //# sourceMappingURL=form-action-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-action-engine.js","sourceRoot":"","sources":["../src/form-action-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export type FormFieldError = {
2
+ name: string;
3
+ message: string;
4
+ };
5
+ export type FormActionResult = {
6
+ ok: boolean;
7
+ error?: unknown;
8
+ field_errors?: FormFieldError[];
9
+ };
10
+ export type FormAction<TContext = unknown> = (context: TContext, formData: FormData, params: URLSearchParams) => Promise<FormActionResult | void> | FormActionResult | void;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=form-actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-actions.js","sourceRoot":"","sources":["../src/form-actions.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export declare function initFormVisibility(): () => void;
@@ -0,0 +1,109 @@
1
+ import { ATTR, SEL } from "./attrs.js";
2
+ import { readField } from "./helpers/form-field.js";
3
+ import { onElement } from "./dom-observer.js";
4
+ const TRANSITION_MS = 200;
5
+ function parseConditions(attr) {
6
+ return attr
7
+ .split(",")
8
+ .map((pair) => {
9
+ const [name, value] = pair.split(":");
10
+ return { name: name?.trim() ?? "", value: value?.trim() ?? "" };
11
+ })
12
+ .filter((p) => p.name && p.value);
13
+ }
14
+ function matchesAny(scope, conditions) {
15
+ return conditions.some(({ name, value }) => readField(scope, name) === value);
16
+ }
17
+ const bindings = new WeakMap();
18
+ function setupVisibility(el) {
19
+ if (bindings.has(el))
20
+ return;
21
+ const attr = el.getAttribute(ATTR.visibleWhen);
22
+ if (!attr)
23
+ return;
24
+ const scope = el.closest(SEL.formScopeOrForm);
25
+ if (!scope) {
26
+ console.warn(`[${ATTR.visibleWhen}] element is not inside a <form> or [${ATTR.formScope}]:`, el);
27
+ return;
28
+ }
29
+ const conditions = parseConditions(attr);
30
+ el.style.transition = "none";
31
+ el.style.opacity = "0";
32
+ el.style.display = "none";
33
+ el.style.pointerEvents = "none";
34
+ el.setAttribute("inert", "");
35
+ el.setAttribute("aria-hidden", "true");
36
+ let lastState = false;
37
+ let hideTimer;
38
+ function show() {
39
+ if (hideTimer !== undefined) {
40
+ clearTimeout(hideTimer);
41
+ hideTimer = undefined;
42
+ }
43
+ el.removeAttribute("inert");
44
+ el.removeAttribute("aria-hidden");
45
+ el.style.display = "";
46
+ el.style.pointerEvents = "";
47
+ requestAnimationFrame(() => {
48
+ el.style.opacity = "1";
49
+ });
50
+ }
51
+ function hide() {
52
+ el.style.opacity = "0";
53
+ el.style.pointerEvents = "none";
54
+ el.setAttribute("inert", "");
55
+ el.setAttribute("aria-hidden", "true");
56
+ hideTimer = setTimeout(() => {
57
+ el.style.display = "none";
58
+ hideTimer = undefined;
59
+ }, TRANSITION_MS);
60
+ }
61
+ function evaluate() {
62
+ const shouldShow = matchesAny(scope, conditions);
63
+ if (shouldShow === lastState)
64
+ return;
65
+ lastState = shouldShow;
66
+ if (shouldShow)
67
+ show();
68
+ else
69
+ hide();
70
+ }
71
+ scope.addEventListener("change", evaluate);
72
+ scope.addEventListener("input", evaluate);
73
+ requestAnimationFrame(() => {
74
+ el.style.transition = `opacity ${TRANSITION_MS}ms ease`;
75
+ evaluate();
76
+ });
77
+ bindings.set(el, {
78
+ el,
79
+ scope,
80
+ conditions,
81
+ evaluate,
82
+ cleanup: () => {
83
+ scope.removeEventListener("change", evaluate);
84
+ scope.removeEventListener("input", evaluate);
85
+ if (hideTimer !== undefined)
86
+ clearTimeout(hideTimer);
87
+ },
88
+ });
89
+ }
90
+ export function initFormVisibility() {
91
+ const tracked = [];
92
+ const unbind = onElement(SEL.visibleWhen, (el) => {
93
+ if (!(el instanceof HTMLElement))
94
+ return;
95
+ tracked.push(el);
96
+ setupVisibility(el);
97
+ });
98
+ return () => {
99
+ unbind();
100
+ tracked.forEach((el) => {
101
+ const b = bindings.get(el);
102
+ if (b) {
103
+ b.cleanup();
104
+ bindings.delete(el);
105
+ }
106
+ });
107
+ };
108
+ }
109
+ //# sourceMappingURL=form-visibility.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-visibility.js","sourceRoot":"","sources":["../src/form-visibility.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,aAAa,GAAG,GAAG,CAAC;AAI1B,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,IAAI;SACR,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAa,EAAE;QACvB,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;IAClE,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB,EAAE,UAAuB;IAC5D,OAAO,UAAU,CAAC,IAAI,CACpB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,KAAK,CACtD,CAAC;AACJ,CAAC;AAUD,MAAM,QAAQ,GAAG,IAAI,OAAO,EAAwB,CAAC;AAErD,SAAS,eAAe,CAAC,EAAe;IACtC,IAAI,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAAE,OAAO;IAE7B,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI;QAAE,OAAO;IAElB,MAAM,KAAK,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CACV,IAAI,IAAI,CAAC,WAAW,wCAAwC,IAAI,CAAC,SAAS,IAAI,EAC9E,EAAE,CACH,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAEzC,EAAE,CAAC,KAAK,CAAC,UAAU,GAAG,MAAM,CAAC;IAC7B,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;IACvB,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;IAC1B,EAAE,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;IAChC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC7B,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAEvC,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,SAAoD,CAAC;IAEzD,SAAS,IAAI;QACX,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,YAAY,CAAC,SAAS,CAAC,CAAC;YACxB,SAAS,GAAG,SAAS,CAAC;QACxB,CAAC;QACD,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC5B,EAAE,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;QAClC,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;QACtB,EAAE,CAAC,KAAK,CAAC,aAAa,GAAG,EAAE,CAAC;QAC5B,qBAAqB,CAAC,GAAG,EAAE;YACzB,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,SAAS,IAAI;QACX,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;QACvB,EAAE,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;QAChC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC7B,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACvC,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAC1B,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;YAC1B,SAAS,GAAG,SAAS,CAAC;QACxB,CAAC,EAAE,aAAa,CAAC,CAAC;IACpB,CAAC;IAED,SAAS,QAAQ;QACf,MAAM,UAAU,GAAG,UAAU,CAAC,KAAM,EAAE,UAAU,CAAC,CAAC;QAClD,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO;QACrC,SAAS,GAAG,UAAU,CAAC;QACvB,IAAI,UAAU;YAAE,IAAI,EAAE,CAAC;;YAClB,IAAI,EAAE,CAAC;IACd,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC3C,KAAK,CAAC,gBAAgB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAE1C,qBAAqB,CAAC,GAAG,EAAE;QACzB,EAAE,CAAC,KAAK,CAAC,UAAU,GAAG,WAAW,aAAa,SAAS,CAAC;QACxD,QAAQ,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE;QACf,EAAE;QACF,KAAK;QACL,UAAU;QACV,QAAQ;QACR,OAAO,EAAE,GAAG,EAAE;YACZ,KAAK,CAAC,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC9C,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC7C,IAAI,SAAS,KAAK,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;QACvD,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE;QAC/C,IAAI,CAAC,CAAC,EAAE,YAAY,WAAW,CAAC;YAAE,OAAO;QACzC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,eAAe,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,OAAO,GAAG,EAAE;QACV,MAAM,EAAE,CAAC;QACT,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;YACrB,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC3B,IAAI,CAAC,EAAE,CAAC;gBACN,CAAC,CAAC,OAAO,EAAE,CAAC;gBACZ,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Set textContent on every [gg-field] descendant of `root` to the value
3
+ * at that field's dot-path on `record`. Null / missing values are left
4
+ * as-is (keeps whatever the markup's default content was).
5
+ */
6
+ export declare function populateFields(root: Element, record: unknown): void;
7
+ /**
8
+ * Write a normalized switch state onto an element.
9
+ * null / undefined become "" so gg-case="" can serve as the empty/default.
10
+ */
11
+ export declare function setSwitchState(el: Element, value: unknown): void;
12
+ /**
13
+ * Show the [gg-case] child whose value matches the container's current
14
+ * gg-switch-state; hide the rest with display:none.
15
+ */
16
+ export declare function applySwitchState(container: Element): void;
@@ -0,0 +1,39 @@
1
+ import { getPath } from "./path.js";
2
+ /**
3
+ * Set textContent on every [gg-field] descendant of `root` to the value
4
+ * at that field's dot-path on `record`. Null / missing values are left
5
+ * as-is (keeps whatever the markup's default content was).
6
+ */
7
+ export function populateFields(root, record) {
8
+ root.querySelectorAll("[gg-field]").forEach((el) => {
9
+ const path = el.getAttribute("gg-field");
10
+ if (!path)
11
+ return;
12
+ const value = getPath(record, path);
13
+ if (value != null)
14
+ el.textContent = String(value);
15
+ });
16
+ }
17
+ /**
18
+ * Write a normalized switch state onto an element.
19
+ * null / undefined become "" so gg-case="" can serve as the empty/default.
20
+ */
21
+ export function setSwitchState(el, value) {
22
+ el.setAttribute("gg-switch-state", value == null ? "" : String(value));
23
+ }
24
+ /**
25
+ * Show the [gg-case] child whose value matches the container's current
26
+ * gg-switch-state; hide the rest with display:none.
27
+ */
28
+ export function applySwitchState(container) {
29
+ const state = container.getAttribute("gg-switch-state") ?? "";
30
+ Array.from(container.children).forEach((child) => {
31
+ if (!(child instanceof HTMLElement))
32
+ return;
33
+ if (!child.hasAttribute("gg-case"))
34
+ return;
35
+ const match = child.getAttribute("gg-case") === state;
36
+ child.style.display = match ? "" : "none";
37
+ });
38
+ }
39
+ //# sourceMappingURL=dom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/helpers/dom.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,IAAa,EAAE,MAAe;IAC3D,IAAI,CAAC,gBAAgB,CAAc,YAAY,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;QAC9D,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACpC,IAAI,KAAK,IAAI,IAAI;YAAE,EAAE,CAAC,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,EAAW,EAAE,KAAc;IACxD,EAAE,CAAC,YAAY,CAAC,iBAAiB,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAAkB;IACjD,MAAM,KAAK,GAAG,SAAS,CAAC,YAAY,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IAC9D,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QAC/C,IAAI,CAAC,CAAC,KAAK,YAAY,WAAW,CAAC;YAAE,OAAO;QAC5C,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC;YAAE,OAAO;QAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC;QACtD,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,19 @@
1
+ export type FieldInput = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
2
+ /**
3
+ * Find every named input/select/textarea matching `name` within `scope`.
4
+ * Used by the data engine, form-action engine, and form-visibility — anywhere
5
+ * we need to read or write a form field by its `name` attribute.
6
+ */
7
+ export declare function findInputs(scope: ParentNode, name: string): FieldInput[];
8
+ /**
9
+ * Read the current value of a named field. For radio/checkbox groups, returns
10
+ * the value of the checked input (or null if none checked). Returns null when
11
+ * no matching input exists. Trimmed for text-like inputs.
12
+ */
13
+ export declare function readField(scope: ParentNode, name: string): string | null;
14
+ /**
15
+ * Write a value into every input matching `name`, dispatching input/change so
16
+ * downstream listeners (visibility, query-bind) react. Skipped when value is
17
+ * null/undefined, so callers can pass `getPath(record, name)` directly.
18
+ */
19
+ export declare function writeField(scope: ParentNode, name: string, value: unknown): void;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Find every named input/select/textarea matching `name` within `scope`.
3
+ * Used by the data engine, form-action engine, and form-visibility — anywhere
4
+ * we need to read or write a form field by its `name` attribute.
5
+ */
6
+ export function findInputs(scope, name) {
7
+ const escaped = CSS.escape(name);
8
+ return Array.from(scope.querySelectorAll(`input[name="${escaped}"], select[name="${escaped}"], textarea[name="${escaped}"]`));
9
+ }
10
+ /**
11
+ * Read the current value of a named field. For radio/checkbox groups, returns
12
+ * the value of the checked input (or null if none checked). Returns null when
13
+ * no matching input exists. Trimmed for text-like inputs.
14
+ */
15
+ export function readField(scope, name) {
16
+ const inputs = findInputs(scope, name);
17
+ if (!inputs.length)
18
+ return null;
19
+ const first = inputs[0];
20
+ const type = (first.getAttribute("type") || "").toLowerCase();
21
+ if (type === "radio" || type === "checkbox") {
22
+ for (const input of inputs) {
23
+ if (input instanceof HTMLInputElement && input.checked) {
24
+ return input.value;
25
+ }
26
+ }
27
+ return null;
28
+ }
29
+ return first.value.trim();
30
+ }
31
+ /**
32
+ * Write a value into every input matching `name`, dispatching input/change so
33
+ * downstream listeners (visibility, query-bind) react. Skipped when value is
34
+ * null/undefined, so callers can pass `getPath(record, name)` directly.
35
+ */
36
+ export function writeField(scope, name, value) {
37
+ if (value == null)
38
+ return;
39
+ findInputs(scope, name).forEach((el) => {
40
+ if (el instanceof HTMLInputElement) {
41
+ if (el.type === "checkbox") {
42
+ el.checked = Boolean(value);
43
+ }
44
+ else if (el.type === "radio") {
45
+ el.checked = String(el.value) === String(value);
46
+ }
47
+ else {
48
+ el.value = String(value);
49
+ }
50
+ }
51
+ else {
52
+ el.value = String(value);
53
+ }
54
+ el.dispatchEvent(new Event("input", { bubbles: true }));
55
+ el.dispatchEvent(new Event("change", { bubbles: true }));
56
+ });
57
+ }
58
+ //# sourceMappingURL=form-field.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-field.js","sourceRoot":"","sources":["../../src/helpers/form-field.ts"],"names":[],"mappings":"AAKA;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,KAAiB,EAAE,IAAY;IACxD,MAAM,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,IAAI,CACf,KAAK,CAAC,gBAAgB,CACpB,eAAe,OAAO,oBAAoB,OAAO,sBAAsB,OAAO,IAAI,CACnF,CACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS,CAAC,KAAiB,EAAE,IAAY;IACvD,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACvC,IAAI,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEhC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9D,IAAI,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QAC5C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,YAAY,gBAAgB,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBACvD,OAAO,KAAK,CAAC,KAAK,CAAC;YACrB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CACxB,KAAiB,EACjB,IAAY,EACZ,KAAc;IAEd,IAAI,KAAK,IAAI,IAAI;QAAE,OAAO;IAC1B,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;QACrC,IAAI,EAAE,YAAY,gBAAgB,EAAE,CAAC;YACnC,IAAI,EAAE,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC3B,EAAE,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;iBAAM,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC/B,EAAE,CAAC,OAAO,GAAG,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC;YAClD,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC;QACD,EAAE,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ /** Resolve a dot-path on an object, e.g. getPath(row, "school.name"). */
2
+ export declare function getPath(obj: unknown, path: string): unknown;
@@ -0,0 +1,9 @@
1
+ /** Resolve a dot-path on an object, e.g. getPath(row, "school.name"). */
2
+ export function getPath(obj, path) {
3
+ return path.split(".").reduce((acc, key) => {
4
+ if (acc == null)
5
+ return undefined;
6
+ return acc[key];
7
+ }, obj);
8
+ }
9
+ //# sourceMappingURL=path.js.map