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
package/README.md CHANGED
@@ -318,6 +318,39 @@ app.addAction("delete_post", async ({ sb }, { id }) => {
318
318
  });
319
319
  ```
320
320
 
321
+ ### Loading states
322
+
323
+ While an action, query, or form action is in flight, the engine sets `gg-loading="true"` on the relevant element so you can style spinners, skeletons, or disabled visuals purely in CSS.
324
+
325
+ | Trigger | Where `gg-loading` is set | Disabled? |
326
+ |---|---|---|
327
+ | `gg-action` | The trigger element itself | Native `disabled` is set if it's a `<button>` or `<input>` |
328
+ | `gg-data` / `gg-data-list` / `gg-data-form` | The container | n/a (not click-triggered) |
329
+ | `gg-form-action` | The `<form>` and every submit control inside it (`button[type="submit"]`, untyped `<button>`, `input[type="submit"]`) | Submit controls get native `disabled` |
330
+
331
+ Re-clicks on a loading `gg-action` and re-submits on a loading `gg-form-action` are ignored. The attribute is removed in a `finally` block, so it's cleared even if the handler throws.
332
+
333
+ Style with CSS:
334
+
335
+ ```css
336
+ [gg-loading] { opacity: 0.6; pointer-events: none; }
337
+ [gg-loading]::after { content: " ⟳"; }
338
+ ```
339
+
340
+ ### Confirm prompts
341
+
342
+ Add `gg-confirm` to a `gg-action` trigger or `gg-form-action` form to require a `window.confirm` dialog before the handler runs. If the user cancels, the action is skipped (and form submission is prevented). Customize the prompt text with `gg-confirm-text`; if omitted it defaults to `"Are you sure?"`.
343
+
344
+ ```html
345
+ <button gg-action="delete_post" gg-confirm gg-confirm-text="Delete this post?">
346
+ Delete
347
+ </button>
348
+
349
+ <form gg-form-action="wipe_account" gg-confirm gg-confirm-text="This cannot be undone. Continue?">
350
+ ...
351
+ </form>
352
+ ```
353
+
321
354
  ## Config
322
355
 
323
356
  ### `init(options)`
@@ -0,0 +1,2 @@
1
+ import type { ActionEngineDeps } from "./engine-deps.js";
2
+ export declare function initActionEngine<TContext>(deps: ActionEngineDeps<TContext>): () => void;
@@ -0,0 +1,97 @@
1
+ import { ATTR, SEL } from "./attrs.js";
2
+ import { runHandler } from "./helpers/run-handler.js";
3
+ import { runWithLoading } from "./helpers/run-with-loading.js";
4
+ import { getParams } from "./query-params.js";
5
+ function parseActionData(el) {
6
+ const attr = el.getAttribute(ATTR.actionData);
7
+ if (!attr)
8
+ return {};
9
+ const data = {};
10
+ attr
11
+ .split(",")
12
+ .filter(Boolean)
13
+ .forEach((pair) => {
14
+ const [key, value] = pair.split(":");
15
+ if (key?.trim())
16
+ data[key.trim()] = value?.trim() ?? "";
17
+ });
18
+ return data;
19
+ }
20
+ function findRecord(el) {
21
+ let node = el.parentElement;
22
+ while (node) {
23
+ if (node.__ggRecord)
24
+ return node.__ggRecord;
25
+ node = node.parentElement;
26
+ }
27
+ return null;
28
+ }
29
+ async function handleAction(el, deps) {
30
+ if (el.hasAttribute(ATTR.loading))
31
+ return;
32
+ const id = el.getAttribute(ATTR.action);
33
+ if (!id)
34
+ return;
35
+ const action = deps.actions[id];
36
+ if (!action) {
37
+ console.warn(`[gg-action] no action registered for "${id}"`);
38
+ deps.emitError({
39
+ prefix: "[gg-action]",
40
+ id,
41
+ error: "no action registered",
42
+ fields: { trigger: el },
43
+ });
44
+ return;
45
+ }
46
+ if (el.hasAttribute(ATTR.confirm)) {
47
+ const text = el.getAttribute(ATTR.confirmText) || "Are you sure?";
48
+ if (!window.confirm(text))
49
+ return;
50
+ }
51
+ const record = findRecord(el);
52
+ const explicit = parseActionData(el);
53
+ const data = record ? { ...record, ...explicit } : explicit;
54
+ const params = getParams();
55
+ const result = await runWithLoading([el], () => runHandler({
56
+ prefix: "[gg-action]",
57
+ id,
58
+ fields: { trigger: el, data, params: Object.fromEntries(params) },
59
+ debug: deps.debug,
60
+ emitError: deps.emitError,
61
+ }, () => action(deps.context, data, params)));
62
+ if (!result.ok)
63
+ return;
64
+ if (result.value && result.value.ok === false) {
65
+ const failure = result.value;
66
+ console.warn(`[gg-action] "${id}" failed:`, failure.error ?? "unknown error");
67
+ deps.emitError({
68
+ prefix: "[gg-action]",
69
+ id,
70
+ error: failure.error ?? "unknown error",
71
+ fields: { trigger: el, data },
72
+ });
73
+ }
74
+ }
75
+ export function initActionEngine(deps) {
76
+ const onClick = (e) => {
77
+ const target = e.target;
78
+ if (!(target instanceof Element))
79
+ return;
80
+ const trigger = target.closest(SEL.action);
81
+ if (trigger)
82
+ handleAction(trigger, deps);
83
+ };
84
+ const onShadowClick = (e) => {
85
+ const detail = e.detail;
86
+ const trigger = detail?.target?.closest?.(SEL.action);
87
+ if (trigger)
88
+ handleAction(trigger, deps);
89
+ };
90
+ document.addEventListener("click", onClick);
91
+ document.addEventListener("gg:shadow:click", onShadowClick);
92
+ return () => {
93
+ document.removeEventListener("click", onClick);
94
+ document.removeEventListener("gg:shadow:click", onShadowClick);
95
+ };
96
+ }
97
+ //# sourceMappingURL=action-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"action-engine.js","sourceRoot":"","sources":["../src/action-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export type ActionResult = {
2
+ ok: boolean;
3
+ error?: unknown;
4
+ };
5
+ export type Action<TContext = unknown, TData extends Record<string, unknown> = Record<string, unknown>> = (context: TContext, data: TData, params: URLSearchParams) => Promise<ActionResult | void> | ActionResult | void;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Single source of truth for every gg-* attribute the library reads or writes.
3
+ * Engines should reference these constants instead of inline string literals so
4
+ * the attribute vocabulary stays discoverable and renameable.
5
+ */
6
+ export declare const ATTR: {
7
+ readonly action: "gg-action";
8
+ readonly actionData: "gg-action-data";
9
+ readonly formAction: "gg-form-action";
10
+ readonly data: "gg-data";
11
+ readonly dataList: "gg-data-list";
12
+ readonly dataForm: "gg-data-form";
13
+ readonly dataOn: "gg-data-on";
14
+ readonly dataKey: "gg-data-key";
15
+ readonly dataValue: "gg-data-value";
16
+ readonly field: "gg-field";
17
+ readonly listTemplate: "gg-list-template";
18
+ readonly formFieldError: "gg-form-field-error";
19
+ readonly formFieldInvalid: "gg-form-field-invalid";
20
+ readonly formError: "gg-form-error";
21
+ readonly formErrorList: "gg-form-error-list";
22
+ readonly formScope: "gg-form-scope";
23
+ readonly switchState: "gg-switch-state";
24
+ readonly switchField: "gg-switch-field";
25
+ readonly switchQuery: "gg-switch-query";
26
+ readonly case: "gg-case";
27
+ readonly visibleWhen: "gg-visible-when";
28
+ readonly queryBind: "gg-query-bind";
29
+ readonly queryDebounce: "gg-query-debounce";
30
+ readonly querySet: "gg-query-set";
31
+ readonly queryRemove: "gg-query-remove";
32
+ readonly loading: "gg-loading";
33
+ readonly confirm: "gg-confirm";
34
+ readonly confirmText: "gg-confirm-text";
35
+ readonly auth: "gg-auth";
36
+ readonly role: "gg-role";
37
+ };
38
+ export declare const SEL: {
39
+ readonly action: "[gg-action]";
40
+ readonly formAction: "form[gg-form-action]";
41
+ readonly data: "[gg-data]";
42
+ readonly dataList: "[gg-data-list]";
43
+ readonly dataForm: "[gg-data-form]";
44
+ readonly dataAny: "[gg-data], [gg-data-list], [gg-data-form]";
45
+ readonly dataAnyOn: "[gg-data][gg-data-on], [gg-data-list][gg-data-on], [gg-data-form][gg-data-on]";
46
+ readonly dataKey: "[gg-data-key]";
47
+ readonly field: "[gg-field]";
48
+ readonly listTemplate: "[gg-list-template]";
49
+ readonly switchState: "[gg-switch-state]";
50
+ readonly switchField: "[gg-switch-field]";
51
+ readonly switchQuery: "[gg-switch-query]";
52
+ readonly visibleWhen: "[gg-visible-when]";
53
+ readonly queryBind: "[gg-query-bind]";
54
+ readonly formScopeOrForm: "[gg-form-scope], form";
55
+ readonly formFieldInvalid: "[gg-form-field-invalid]";
56
+ readonly formFieldError: "[gg-form-field-error]";
57
+ readonly formError: "[gg-form-error]";
58
+ readonly formErrorList: "[gg-form-error-list]";
59
+ };
package/dist/attrs.js ADDED
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Single source of truth for every gg-* attribute the library reads or writes.
3
+ * Engines should reference these constants instead of inline string literals so
4
+ * the attribute vocabulary stays discoverable and renameable.
5
+ */
6
+ export const ATTR = {
7
+ // Actions
8
+ action: "gg-action",
9
+ actionData: "gg-action-data",
10
+ formAction: "gg-form-action",
11
+ // Data binding
12
+ data: "gg-data",
13
+ dataList: "gg-data-list",
14
+ dataForm: "gg-data-form",
15
+ dataOn: "gg-data-on",
16
+ dataKey: "gg-data-key",
17
+ dataValue: "gg-data-value",
18
+ field: "gg-field",
19
+ listTemplate: "gg-list-template",
20
+ // Form errors
21
+ formFieldError: "gg-form-field-error",
22
+ formFieldInvalid: "gg-form-field-invalid",
23
+ formError: "gg-form-error",
24
+ formErrorList: "gg-form-error-list",
25
+ formScope: "gg-form-scope",
26
+ // Switcher
27
+ switchState: "gg-switch-state",
28
+ switchField: "gg-switch-field",
29
+ switchQuery: "gg-switch-query",
30
+ case: "gg-case",
31
+ // Visibility
32
+ visibleWhen: "gg-visible-when",
33
+ // URL params
34
+ queryBind: "gg-query-bind",
35
+ queryDebounce: "gg-query-debounce",
36
+ querySet: "gg-query-set",
37
+ queryRemove: "gg-query-remove",
38
+ // Status
39
+ loading: "gg-loading",
40
+ confirm: "gg-confirm",
41
+ confirmText: "gg-confirm-text",
42
+ auth: "gg-auth",
43
+ role: "gg-role",
44
+ };
45
+ export const SEL = {
46
+ action: `[${ATTR.action}]`,
47
+ formAction: `form[${ATTR.formAction}]`,
48
+ data: `[${ATTR.data}]`,
49
+ dataList: `[${ATTR.dataList}]`,
50
+ dataForm: `[${ATTR.dataForm}]`,
51
+ dataAny: `[${ATTR.data}], [${ATTR.dataList}], [${ATTR.dataForm}]`,
52
+ dataAnyOn: `[${ATTR.data}][${ATTR.dataOn}], [${ATTR.dataList}][${ATTR.dataOn}], [${ATTR.dataForm}][${ATTR.dataOn}]`,
53
+ dataKey: `[${ATTR.dataKey}]`,
54
+ field: `[${ATTR.field}]`,
55
+ listTemplate: `[${ATTR.listTemplate}]`,
56
+ switchState: `[${ATTR.switchState}]`,
57
+ switchField: `[${ATTR.switchField}]`,
58
+ switchQuery: `[${ATTR.switchQuery}]`,
59
+ visibleWhen: `[${ATTR.visibleWhen}]`,
60
+ queryBind: `[${ATTR.queryBind}]`,
61
+ formScopeOrForm: `[${ATTR.formScope}], form`,
62
+ formFieldInvalid: `[${ATTR.formFieldInvalid}]`,
63
+ formFieldError: `[${ATTR.formFieldError}]`,
64
+ formError: `[${ATTR.formError}]`,
65
+ formErrorList: `[${ATTR.formErrorList}]`,
66
+ };
67
+ //# sourceMappingURL=attrs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attrs.js","sourceRoot":"","sources":["../src/attrs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,UAAU;IACV,MAAM,EAAE,WAAW;IACnB,UAAU,EAAE,gBAAgB;IAC5B,UAAU,EAAE,gBAAgB;IAE5B,eAAe;IACf,IAAI,EAAE,SAAS;IACf,QAAQ,EAAE,cAAc;IACxB,QAAQ,EAAE,cAAc;IACxB,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,aAAa;IACtB,SAAS,EAAE,eAAe;IAC1B,KAAK,EAAE,UAAU;IACjB,YAAY,EAAE,kBAAkB;IAEhC,cAAc;IACd,cAAc,EAAE,qBAAqB;IACrC,gBAAgB,EAAE,uBAAuB;IACzC,SAAS,EAAE,eAAe;IAC1B,aAAa,EAAE,oBAAoB;IACnC,SAAS,EAAE,eAAe;IAE1B,WAAW;IACX,WAAW,EAAE,iBAAiB;IAC9B,WAAW,EAAE,iBAAiB;IAC9B,WAAW,EAAE,iBAAiB;IAC9B,IAAI,EAAE,SAAS;IAEf,aAAa;IACb,WAAW,EAAE,iBAAiB;IAE9B,aAAa;IACb,SAAS,EAAE,eAAe;IAC1B,aAAa,EAAE,mBAAmB;IAClC,QAAQ,EAAE,cAAc;IACxB,WAAW,EAAE,iBAAiB;IAE9B,SAAS;IACT,OAAO,EAAE,YAAY;IACrB,OAAO,EAAE,YAAY;IACrB,WAAW,EAAE,iBAAiB;IAC9B,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;CACP,CAAC;AAEX,MAAM,CAAC,MAAM,GAAG,GAAG;IACjB,MAAM,EAAE,IAAI,IAAI,CAAC,MAAM,GAAG;IAC1B,UAAU,EAAE,QAAQ,IAAI,CAAC,UAAU,GAAG;IACtC,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,GAAG;IACtB,QAAQ,EAAE,IAAI,IAAI,CAAC,QAAQ,GAAG;IAC9B,QAAQ,EAAE,IAAI,IAAI,CAAC,QAAQ,GAAG;IAC9B,OAAO,EAAE,IAAI,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,GAAG;IACjE,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,OAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,MAAM,OAAO,IAAI,CAAC,QAAQ,KAAK,IAAI,CAAC,MAAM,GAAG;IACnH,OAAO,EAAE,IAAI,IAAI,CAAC,OAAO,GAAG;IAC5B,KAAK,EAAE,IAAI,IAAI,CAAC,KAAK,GAAG;IACxB,YAAY,EAAE,IAAI,IAAI,CAAC,YAAY,GAAG;IACtC,WAAW,EAAE,IAAI,IAAI,CAAC,WAAW,GAAG;IACpC,WAAW,EAAE,IAAI,IAAI,CAAC,WAAW,GAAG;IACpC,WAAW,EAAE,IAAI,IAAI,CAAC,WAAW,GAAG;IACpC,WAAW,EAAE,IAAI,IAAI,CAAC,WAAW,GAAG;IACpC,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,GAAG;IAChC,eAAe,EAAE,IAAI,IAAI,CAAC,SAAS,SAAS;IAC5C,gBAAgB,EAAE,IAAI,IAAI,CAAC,gBAAgB,GAAG;IAC9C,cAAc,EAAE,IAAI,IAAI,CAAC,cAAc,GAAG;IAC1C,SAAS,EAAE,IAAI,IAAI,CAAC,SAAS,GAAG;IAChC,aAAa,EAAE,IAAI,IAAI,CAAC,aAAa,GAAG;CAChC,CAAC"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export type AuthAdapter<TContext = unknown> = {
2
+ getUser: () => string | null | Promise<string | null>;
3
+ onChange?: (cb: (userId: string | null) => void) => void;
4
+ roleQuery?: (context: TContext, userId: string) => Promise<string | null> | string | null;
5
+ };
6
+ export declare function initAuth<TContext>(context: TContext, auth: AuthAdapter<TContext>): Promise<void>;
package/dist/auth.js ADDED
@@ -0,0 +1,28 @@
1
+ import { ATTR } from "./attrs.js";
2
+ export async function initAuth(context, auth) {
3
+ const { getUser, onChange, roleQuery } = auth;
4
+ async function applyAuthAttrs(userId) {
5
+ const body = document.body;
6
+ if (!userId) {
7
+ body.setAttribute(ATTR.auth, "false");
8
+ body.removeAttribute(ATTR.role);
9
+ return;
10
+ }
11
+ body.setAttribute(ATTR.auth, "true");
12
+ if (roleQuery) {
13
+ const role = await roleQuery(context, userId);
14
+ if (role) {
15
+ body.setAttribute(ATTR.role, role);
16
+ }
17
+ else {
18
+ body.removeAttribute(ATTR.role);
19
+ }
20
+ }
21
+ }
22
+ const userId = await getUser();
23
+ applyAuthAttrs(userId ?? null);
24
+ if (onChange) {
25
+ onChange((userId) => applyAuthAttrs(userId ?? null));
26
+ }
27
+ }
28
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAWlC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAAiB,EACjB,IAA2B;IAE3B,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAE9C,KAAK,UAAU,cAAc,CAAC,MAAqB;QACjD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;QAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACtC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACrC,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAC9C,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACrC,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,OAAO,EAAE,CAAC;IAC/B,cAAc,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;IAE/B,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC;IACvD,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function initBridges(): () => void;
@@ -0,0 +1,43 @@
1
+ import { ATTR, SEL } from "./attrs.js";
2
+ import { setSwitchState } from "./helpers/dom.js";
3
+ import { onQueryChanged } from "./query-params.js";
4
+ import { onElement } from "./dom-observer.js";
5
+ export function initBridges() {
6
+ // ---- gg-switch-query: URL params → gg-switch-state ----
7
+ const unsubscribeQuery = onQueryChanged((key, value) => {
8
+ document
9
+ .querySelectorAll(`[${ATTR.switchQuery}="${CSS.escape(key)}"]`)
10
+ .forEach((el) => setSwitchState(el, value));
11
+ });
12
+ // Apply current URL state to every [gg-switch-query] element on the page,
13
+ // including any inserted later via Webflow IX or CMS templates.
14
+ const unbindSwitch = onElement(SEL.switchQuery, (el) => {
15
+ const key = el.getAttribute(ATTR.switchQuery);
16
+ if (!key)
17
+ return;
18
+ const params = new URLSearchParams(window.location.search);
19
+ setSwitchState(el, params.get(key));
20
+ });
21
+ // ---- webflow:emit → Webflow IX ----
22
+ let wfHandler = null;
23
+ const onLoad = () => {
24
+ Webflow.push(() => {
25
+ const wfIx = Webflow.require("ix3");
26
+ wfHandler = (e) => {
27
+ const detail = e.detail;
28
+ if (detail?.event)
29
+ wfIx.emit(detail.event);
30
+ };
31
+ document.addEventListener("webflow:emit", wfHandler);
32
+ });
33
+ };
34
+ window.addEventListener("load", onLoad);
35
+ return () => {
36
+ unsubscribeQuery();
37
+ unbindSwitch();
38
+ window.removeEventListener("load", onLoad);
39
+ if (wfHandler)
40
+ document.removeEventListener("webflow:emit", wfHandler);
41
+ };
42
+ }
43
+ //# sourceMappingURL=bridges.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridges.js","sourceRoot":"","sources":["../src/bridges.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAE9C,MAAM,UAAU,WAAW;IACzB,0DAA0D;IAC1D,MAAM,gBAAgB,GAAG,cAAc,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACrD,QAAQ;aACL,gBAAgB,CAAC,IAAI,IAAI,CAAC,WAAW,KAAK,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;aAC9D,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,0EAA0E;IAC1E,gEAAgE;IAChE,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,EAAE;QACrD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9C,IAAI,CAAC,GAAG;YAAE,OAAO;QACjB,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3D,cAAc,CAAC,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,sCAAsC;IACtC,IAAI,SAAS,GAAgC,IAAI,CAAC;IAClD,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;YAChB,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpC,SAAS,GAAG,CAAC,CAAQ,EAAE,EAAE;gBACvB,MAAM,MAAM,GAAI,CAAoC,CAAC,MAAM,CAAC;gBAC5D,IAAI,MAAM,EAAE,KAAK;oBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7C,CAAC,CAAC;YACF,QAAQ,CAAC,gBAAgB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IACF,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExC,OAAO,GAAG,EAAE;QACV,gBAAgB,EAAE,CAAC;QACnB,YAAY,EAAE,CAAC;QACf,MAAM,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,IAAI,SAAS;YAAE,QAAQ,CAAC,mBAAmB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;IACzE,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { DataEngineDeps } from "./engine-deps.js";
2
+ export declare function initDataEngine<TContext>(deps: DataEngineDeps<TContext>): () => void;
@@ -0,0 +1,153 @@
1
+ import { ATTR, SEL } from "./attrs.js";
2
+ import { getPath } from "./helpers/path.js";
3
+ import { populateFields, setSwitchState, applySwitchState, } from "./helpers/dom.js";
4
+ import { writeField } from "./helpers/form-field.js";
5
+ import { runHandler } from "./helpers/run-handler.js";
6
+ import { runWithLoading } from "./helpers/run-with-loading.js";
7
+ import { onElement } from "./dom-observer.js";
8
+ import { onQueryChanged, getParams } from "./query-params.js";
9
+ function applySwitchFields(root, record) {
10
+ root.querySelectorAll(SEL.switchField).forEach((el) => {
11
+ const path = el.getAttribute(ATTR.switchField);
12
+ if (!path)
13
+ return;
14
+ const value = getPath(record, path);
15
+ setSwitchState(el, value);
16
+ applySwitchState(el);
17
+ });
18
+ }
19
+ function queryDeep(root, selector) {
20
+ const results = [...root.querySelectorAll(selector)];
21
+ root.querySelectorAll("*").forEach((el) => {
22
+ if (el.shadowRoot)
23
+ results.push(...queryDeep(el.shadowRoot, selector));
24
+ });
25
+ return results;
26
+ }
27
+ function applyDataValues(root, record) {
28
+ queryDeep(root, SEL.dataKey).forEach((el) => {
29
+ const path = el.getAttribute(ATTR.dataKey);
30
+ const value = path ? getPath(record, path) : record;
31
+ if (value === undefined)
32
+ return;
33
+ el.setAttribute(ATTR.dataValue, JSON.stringify(value));
34
+ });
35
+ }
36
+ function populateFormFields(root, record) {
37
+ root
38
+ .querySelectorAll("input[name], select[name], textarea[name]")
39
+ .forEach((el) => {
40
+ const name = el.getAttribute("name");
41
+ if (!name)
42
+ return;
43
+ writeField(root, name, getPath(record, name));
44
+ });
45
+ }
46
+ async function runQuery(container, deps) {
47
+ const isList = container.hasAttribute(ATTR.dataList);
48
+ const isForm = container.hasAttribute(ATTR.dataForm);
49
+ const id = container.getAttribute(isList ? ATTR.dataList : isForm ? ATTR.dataForm : ATTR.data);
50
+ if (!id)
51
+ return;
52
+ const query = deps.queries[id];
53
+ if (!query) {
54
+ console.warn(`[gg-data] no query registered for "${id}"`);
55
+ deps.emitError({
56
+ prefix: "[gg-data]",
57
+ id,
58
+ error: "no query registered",
59
+ fields: { container },
60
+ });
61
+ return;
62
+ }
63
+ const params = getParams();
64
+ const handlerResult = await runWithLoading([container], () => runHandler({
65
+ prefix: "[gg-data]",
66
+ id,
67
+ fields: { container, params: Object.fromEntries(params) },
68
+ debug: deps.debug,
69
+ emitError: deps.emitError,
70
+ }, () => query(deps.context, params)));
71
+ if (!handlerResult.ok)
72
+ return;
73
+ const result = handlerResult.value;
74
+ if (result === undefined)
75
+ return;
76
+ if (isList) {
77
+ if (!Array.isArray(result)) {
78
+ console.warn(`[gg-data-list] query "${id}" did not return an array`);
79
+ return;
80
+ }
81
+ const template = container.querySelector(SEL.listTemplate);
82
+ if (!template) {
83
+ console.warn(`[gg-data-list] no [${ATTR.listTemplate}] inside "${id}"`);
84
+ return;
85
+ }
86
+ Array.from(container.children).forEach((child) => {
87
+ if (child !== template)
88
+ child.remove();
89
+ });
90
+ result.forEach((record) => {
91
+ const clone = template.cloneNode(true);
92
+ clone.removeAttribute(ATTR.listTemplate);
93
+ clone.setAttribute(ATTR.querySet, `modal:view,id:${record.id}`);
94
+ clone.style.display = "flex";
95
+ if (record?.id != null)
96
+ clone.id = String(record.id);
97
+ clone.__ggRecord = record;
98
+ populateFields(clone, record);
99
+ applySwitchFields(clone, record);
100
+ applyDataValues(clone, record);
101
+ container.appendChild(clone);
102
+ });
103
+ }
104
+ else if (isForm) {
105
+ if (Array.isArray(result)) {
106
+ console.warn(`[gg-data-form] query "${id}" returned an array; expected a single record`);
107
+ return;
108
+ }
109
+ if (!result)
110
+ return;
111
+ const record = result;
112
+ container.__ggRecord = record;
113
+ populateFormFields(container, record);
114
+ applyDataValues(container, record);
115
+ }
116
+ else {
117
+ if (Array.isArray(result)) {
118
+ console.warn(`[gg-data] query "${id}" returned an array; use gg-data-list instead`);
119
+ return;
120
+ }
121
+ if (!result)
122
+ return;
123
+ const record = result;
124
+ container.__ggRecord = record;
125
+ populateFields(container, record);
126
+ applySwitchFields(container, record);
127
+ applyDataValues(container, record);
128
+ }
129
+ }
130
+ export function initDataEngine(deps) {
131
+ const seen = new WeakSet();
132
+ const unbind = onElement(SEL.dataAny, (el) => {
133
+ if (seen.has(el))
134
+ return;
135
+ seen.add(el);
136
+ runQuery(el, deps);
137
+ });
138
+ const unsubscribe = onQueryChanged((key) => {
139
+ document.querySelectorAll(SEL.dataAnyOn).forEach((c) => {
140
+ const attr = c.getAttribute(ATTR.dataOn);
141
+ if (!attr)
142
+ return;
143
+ const keys = attr.split(",").map((s) => s.trim());
144
+ if (keys.includes(key))
145
+ runQuery(c, deps);
146
+ });
147
+ });
148
+ return () => {
149
+ unbind();
150
+ unsubscribe();
151
+ };
152
+ }
153
+ //# sourceMappingURL=data-engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-engine.js","sourceRoot":"","sources":["../src/data-engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function initDialog(): () => void;
package/dist/dialog.js ADDED
@@ -0,0 +1,93 @@
1
+ import { removeQueryParams, onQueryChanged } from "./query-params.js";
2
+ function stopLenis() {
3
+ if (typeof lenis !== "undefined")
4
+ lenis.stop();
5
+ }
6
+ function startLenis() {
7
+ if (typeof lenis !== "undefined")
8
+ lenis.start();
9
+ }
10
+ function openDialog() {
11
+ const dialog = document.querySelector("dialog");
12
+ if (!dialog)
13
+ return;
14
+ dialog.removeAttribute("aria-hidden");
15
+ dialog.removeAttribute("inert");
16
+ dialog.showModal();
17
+ stopLenis();
18
+ }
19
+ function closeDialog() {
20
+ const dialog = document.querySelector("dialog");
21
+ if (!dialog)
22
+ return;
23
+ dialog.setAttribute("aria-hidden", "true");
24
+ dialog.setAttribute("inert", "");
25
+ dialog.close();
26
+ startLenis();
27
+ }
28
+ function dismissViaUrlOrDirect() {
29
+ const modalParam = new URLSearchParams(window.location.search).get("modal");
30
+ if (modalParam) {
31
+ removeQueryParams(["modal", "id"]);
32
+ }
33
+ else {
34
+ closeDialog();
35
+ }
36
+ }
37
+ function syncDialogToUrl() {
38
+ const modalParam = new URLSearchParams(window.location.search).get("modal");
39
+ if (modalParam) {
40
+ openDialog();
41
+ }
42
+ else {
43
+ closeDialog();
44
+ }
45
+ }
46
+ export function initDialog() {
47
+ const unsubscribe = onQueryChanged((key, value) => {
48
+ if (key !== "modal")
49
+ return;
50
+ if (value) {
51
+ openDialog();
52
+ }
53
+ else {
54
+ closeDialog();
55
+ }
56
+ });
57
+ document.addEventListener("gg:dialog:open", openDialog);
58
+ document.addEventListener("gg:dialog:close", closeDialog);
59
+ const onClick = (e) => {
60
+ const target = e.target;
61
+ if (!(target instanceof HTMLDialogElement))
62
+ return;
63
+ if (!target.matches("dialog[open]"))
64
+ return;
65
+ const rect = target.getBoundingClientRect();
66
+ const outside = e.clientX < rect.left ||
67
+ e.clientX > rect.right ||
68
+ e.clientY < rect.top ||
69
+ e.clientY > rect.bottom;
70
+ if (outside)
71
+ dismissViaUrlOrDirect();
72
+ };
73
+ document.addEventListener("click", onClick);
74
+ const onCancel = (e) => {
75
+ const target = e.target;
76
+ if (!(target instanceof HTMLDialogElement))
77
+ return;
78
+ e.preventDefault();
79
+ dismissViaUrlOrDirect();
80
+ };
81
+ document.addEventListener("cancel", onCancel);
82
+ window.addEventListener("popstate", syncDialogToUrl);
83
+ syncDialogToUrl();
84
+ return () => {
85
+ unsubscribe();
86
+ document.removeEventListener("gg:dialog:open", openDialog);
87
+ document.removeEventListener("gg:dialog:close", closeDialog);
88
+ document.removeEventListener("click", onClick);
89
+ document.removeEventListener("cancel", onCancel);
90
+ window.removeEventListener("popstate", syncDialogToUrl);
91
+ };
92
+ }
93
+ //# sourceMappingURL=dialog.js.map