@loadbare/app 0.9.0 → 0.10.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 (80) hide show
  1. package/README.md +3 -3
  2. package/dist/build/assemble.d.ts.map +1 -1
  3. package/dist/build/assemble.js +74 -66
  4. package/dist/build/assemble.js.map +1 -1
  5. package/dist/build/expand.d.ts.map +1 -1
  6. package/dist/build/expand.js +20 -19
  7. package/dist/build/expand.js.map +1 -1
  8. package/dist/build/locations.d.ts +2 -3
  9. package/dist/build/locations.d.ts.map +1 -1
  10. package/dist/build/locations.js +2 -3
  11. package/dist/build/locations.js.map +1 -1
  12. package/dist/build/pages.d.ts +3 -4
  13. package/dist/build/pages.d.ts.map +1 -1
  14. package/dist/build/pages.js +3 -4
  15. package/dist/build/pages.js.map +1 -1
  16. package/dist/core/lb-constants.d.ts +25 -24
  17. package/dist/core/lb-constants.d.ts.map +1 -1
  18. package/dist/core/lb-constants.js +95 -168
  19. package/dist/core/lb-constants.js.map +1 -1
  20. package/dist/core/lb-types.d.ts +64 -77
  21. package/dist/core/lb-types.d.ts.map +1 -1
  22. package/dist/core/lb-types.js +40 -7
  23. package/dist/core/lb-types.js.map +1 -1
  24. package/dist/hub/lb-apply.d.ts +47 -37
  25. package/dist/hub/lb-apply.d.ts.map +1 -1
  26. package/dist/hub/lb-apply.js +174 -193
  27. package/dist/hub/lb-apply.js.map +1 -1
  28. package/dist/hub/lb-hub.browser.d.ts +1 -1
  29. package/dist/hub/lb-hub.browser.d.ts.map +1 -1
  30. package/dist/hub/lb-hub.browser.js +411 -449
  31. package/dist/hub/lb-hub.browser.js.map +1 -1
  32. package/dist/server/lb-express.d.ts +5 -5
  33. package/dist/server/lb-express.d.ts.map +1 -1
  34. package/dist/server/lb-express.js +35 -66
  35. package/dist/server/lb-express.js.map +1 -1
  36. package/dist/server/lb-server.d.ts +77 -135
  37. package/dist/server/lb-server.d.ts.map +1 -1
  38. package/dist/server/lb-server.js +132 -79
  39. package/dist/server/lb-server.js.map +1 -1
  40. package/docs/TECHREF-1.0.md +861 -587
  41. package/docs/comparison.md +222 -185
  42. package/docs/prior-art.md +15 -14
  43. package/docs/reference/builder.md +9 -3
  44. package/docs/reference/chrome.md +107 -56
  45. package/docs/reference/custom-elements.md +199 -173
  46. package/docs/reference/data-binding.md +374 -374
  47. package/docs/reference/overview.md +12 -10
  48. package/docs/reference/page-files.md +135 -99
  49. package/docs/reference/server.md +2 -2
  50. package/docs/reference/widgets.md +104 -110
  51. package/docs/roadmap.md +32 -39
  52. package/docs/terms-of-art.md +57 -0
  53. package/docs/testing.md +97 -68
  54. package/docs/theory.md +92 -58
  55. package/docs/tutorials/010-pages-and-navigation.md +20 -12
  56. package/docs/tutorials/020-css.md +6 -3
  57. package/docs/tutorials/030-html-decomposition.md +9 -7
  58. package/docs/tutorials/040-displaying-data.md +30 -13
  59. package/docs/tutorials/{050-actions.md → 050-requests.md} +25 -15
  60. package/docs/tutorials/060-custom-element-code.md +17 -16
  61. package/docs/tutorials/065-conditional-rendering.md +34 -23
  62. package/docs/tutorials/070-displaying-a-list.md +29 -21
  63. package/docs/tutorials/072-inserting-into-a-list.md +24 -16
  64. package/docs/tutorials/074-deleting-from-a-list.md +9 -7
  65. package/docs/tutorials/076-updating-a-list-item.md +11 -10
  66. package/docs/tutorials/080-widget-requests.md +71 -43
  67. package/docs/tutorials/090-using-widget-libraries.md +22 -22
  68. package/package.json +1 -1
  69. package/skills/loadbare-app/SKILL.md +178 -122
  70. package/skills/loadbare-app/references/TECHREF-1.0.md +861 -587
  71. package/skills/loadbare-app/references/builder.md +9 -3
  72. package/skills/loadbare-app/references/chrome.md +107 -56
  73. package/skills/loadbare-app/references/custom-elements.md +199 -173
  74. package/skills/loadbare-app/references/data-binding.md +374 -374
  75. package/skills/loadbare-app/references/overview.md +12 -10
  76. package/skills/loadbare-app/references/page-files.md +135 -99
  77. package/skills/loadbare-app/references/server.md +2 -2
  78. package/skills/loadbare-app/references/widgets.md +104 -110
  79. package/docs/analysis-accidental-complexity.md +0 -149
  80. package/docs/analysis-closed-set.md +0 -210
@@ -1,4 +1,4 @@
1
- import { ACTION_ROW_DELETE, ACTION_ROW_INSERT, ACTION_ROW_UPDATE } from "./lb-constants.js";
1
+ import { KIND_ROW, KIND_ROWS } from "./lb-constants.js";
2
2
  /**
3
3
  * One row: its columns, by name.
4
4
  *
@@ -9,9 +9,9 @@ import { ACTION_ROW_DELETE, ACTION_ROW_INSERT, ACTION_ROW_UPDATE } from "./lb-co
9
9
  */
10
10
  export type Row = Record<string, unknown>;
11
11
  /**
12
- * Part of a list — see docs/reference/server.md, "Queries".
12
+ * Part of a `rows` query's answer — see docs/reference/server.md, "Queries".
13
13
  *
14
- * Rows named here arrive or are updated, keys in `drop` are gone, and
14
+ * Rows named here are added or updated, keys in `drop` are removed, and
15
15
  * anything unnamed is left alone: its contents, and its place in whatever
16
16
  * order the widget is keeping. Add and remove are one result rather than two
17
17
  * because the interesting cases are both at once — a row whose sort key
@@ -22,77 +22,51 @@ export interface Patch {
22
22
  rows?: Row[];
23
23
  drop?: unknown[];
24
24
  }
25
+ /** A query's kind, declared by the server and carried by every answer. */
26
+ export type Kind = typeof KIND_ROW | typeof KIND_ROWS;
25
27
  /**
26
- * What a list answers with.
27
- *
28
- * An array is the entire set and therefore also the order: a row whose key
29
- * is not in it is gone. A Patch disturbs only what it names.
30
- *
31
- * `Array.isArray` tells the two apart, which is why no column name has to be
32
- * reserved to carry a discriminant. A list answering with an object is a
33
- * patch, because the declaration already said this name answers with rows.
34
- */
35
- export type ListResult = Row[] | Patch;
36
- export declare function isPatch(result: ListResult): result is Patch;
37
- /**
38
- * What any one name answers with. Which of the two it is comes from the
39
- * query's own declaration, never from inspecting the value.
28
+ * What a `rows` query answers with: all rows, which is also their order, or
29
+ * a patch. `Array.isArray` tells the two apart.
40
30
  */
41
- export type HubResult = Row | ListResult;
31
+ export type RowsResult = Row[] | Patch;
32
+ export declare function isPatch(result: RowsResult): result is Patch;
33
+ /** What any one query answers with, as the application writes it. */
34
+ export type HubResult = Row | RowsResult;
42
35
  /**
43
- * Every response on the data channel is the same shape, whether it is a cold
44
- * start or the narrowest refresh. The hub does not know which case it is in.
45
- *
46
- * A name rides as an object key and is labelled by nothing, which is why the
47
- * response direction never needed a noun for the addressable thing.
36
+ * What application code hands the engine: answers by query name. The engine
37
+ * turns each into a response item, adding the kind and key the query
38
+ * declared.
48
39
  */
49
40
  export type HubData = Record<string, HubResult>;
50
41
  /**
51
- * The three operations — docs/reference/data-binding.md. The set is closed.
52
- *
53
- * `action` carries the value of `lb-action` verbatim, so the attribute, the
54
- * wire field and the CRUD key are one vocabulary with no translation step.
55
- * The scope field is `list` here because all three are list operations: each
56
- * needs a key, and a key exists only on a live row inside a list.
42
+ * One query's answer on the wire: its name, its kind, its key's column name,
43
+ * and exactly one of a row, all rows, or a patch. A patch answers a `rows`
44
+ * query only.
57
45
  */
58
- export type LbOperation = {
59
- action: typeof ACTION_ROW_INSERT;
60
- list: string;
61
- values: Record<string, string>;
62
- } | {
63
- action: typeof ACTION_ROW_DELETE;
64
- list: string;
46
+ export interface ResponseItem {
47
+ query: string;
48
+ kind: Kind;
65
49
  key: string;
66
- } | {
67
- action: typeof ACTION_ROW_UPDATE;
68
- list: string;
69
- key: string;
70
- values: Record<string, string>;
71
- };
50
+ row?: Row;
51
+ rows?: Row[];
52
+ patch?: Patch;
53
+ }
54
+ /** Every response the server sends: a page load and a request alike. */
55
+ export type HubResponse = ResponseItem[];
72
56
  /**
73
- * Everything that is not one of the three.
74
- *
75
- * The name is the application's and is looked up in the page's declared
76
- * actions. What keeps this from being an RPC endpoint is that the name must
77
- * already appear in the page's requests: the browser cannot reach anything the
78
- * page has not published, and there is no argument list — only where the
79
- * interaction happened and, where a control has one, its value.
80
- *
81
- * The scope field is `list` or `row`, whichever attribute scoped the element
82
- * the interaction came from, so an action fired from a single-row scope says
83
- * so. A button carries no value, so the server computes the whole of the new
84
- * state and the browser never displays a number it has not confirmed. A
85
- * `<select>` carries one, because the choice is the interaction.
57
+ * Every request has one shape. The name picks the handler; the rest is
58
+ * present when the hub found it.
86
59
  */
87
- export interface DeclaredAction {
88
- action: string;
89
- list?: string;
90
- row?: string;
60
+ export interface HubRequest {
61
+ name: string;
62
+ query?: string;
91
63
  key?: string;
92
- cell?: string;
93
- value?: string;
64
+ values?: Record<string, string>;
94
65
  }
95
- export type HubRequest = LbOperation | DeclaredAction;
66
+ /** The fields a handler receives: the request, less its name. */
67
+ export type RequestFields = Omit<HubRequest, "name">;
68
+ /** Whether a name is one of the requests Loadbare provides. */
69
+ export declare function isRowRequest(name: string): boolean;
96
70
  /**
97
71
  * A query string with some parms set, and the rest as they were. An empty
98
72
  * value takes its parm out, since empty is every parm's default and a
@@ -100,30 +74,43 @@ export type HubRequest = LbOperation | DeclaredAction;
100
74
  *
101
75
  * One rule on both sides of the wire: the hub applies it to the address bar,
102
76
  * and the server to the query string it loads the page at after a request
103
- * returned `QUERY_PARMS_ROW`. The two must agree, or what the page shows
104
- * would differ from what the address bar says.
77
+ * returned `lb-url`. The two must agree, or what the page shows would differ
78
+ * from what the address bar says.
105
79
  */
106
80
  export declare function withQueryParms(search: URLSearchParams, parms: Record<string, string>): URLSearchParams;
107
81
  /**
108
- * The reserved prefix is the whole of the discriminant. Nothing else tells
109
- * an operation from a declared action, on the wire or anywhere else.
82
+ * A path names a page by its stub, and nothing finer. The bare path resolves
83
+ * to `index`, the same convention a static file server follows.
110
84
  */
111
- export declare function isOperation(request: HubRequest): request is LbOperation;
85
+ export declare function pageNameFor(path: string): string;
112
86
  /**
113
- * The two hooks a list widget may implement, both optional.
87
+ * Where a row for `lb-url` leads, from a page and its query parms.
114
88
  *
115
- * The hub reconciles every list scope itself, so a widget supplies placement
116
- * and scaffolding and nothing else. A scope that implements neither is a
117
- * plain element with a row template inside it, which is why there is no
118
- * repeater widget.
89
+ * A column whose name begins with `lb-` is Loadbare's, and never a query
90
+ * parm; every other column is one. An `lb-path` naming another page enters
91
+ * it with only the parms the row names. Otherwise the named parms are set,
92
+ * or taken out when empty, and the rest are kept.
93
+ *
94
+ * One rule on both sides of the wire: the server loads the page it names,
95
+ * and the hub writes the URL it names. The two must agree, or what the page
96
+ * shows would differ from what the address bar says.
97
+ */
98
+ export declare function nextLocation(page: string, parms: URLSearchParams, row: Row): {
99
+ page: string;
100
+ parms: URLSearchParams;
101
+ moved: boolean;
102
+ };
103
+ /**
104
+ * The two hooks a custom element holding rows may implement, both optional.
119
105
  *
120
- * They are methods on an element the hub does not own, so they carry the
121
- * `lb` prefix that Loadbare reserves for exactly that — see
122
- * docs/reference/custom-elements.md.
106
+ * The hub reconciles every row template itself, so a custom element supplies
107
+ * placement and scaffolding and nothing else. They are methods on an element
108
+ * the hub does not own, so they carry the `lb` prefix Loadbare reserves for
109
+ * exactly that — see docs/reference/custom-elements.md.
123
110
  */
124
- export interface ListHost {
111
+ export interface RowsHost {
125
112
  /**
126
- * Where a row belongs, called with the row detached on its first
113
+ * Where a live row belongs, called with the row detached on its first
127
114
  * appearance. Without it a row lands immediately before the template, so
128
115
  * rows accumulate in the order they arrive.
129
116
  */
@@ -1 +1 @@
1
- {"version":3,"file":"lb-types.d.ts","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EAElB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;GAOG;AACH,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC;AAEvC,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,IAAI,KAAK,CAE3D;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,UAAU,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GACnB;IACE,MAAM,EAAE,OAAO,iBAAiB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,GACD;IAAE,MAAM,EAAE,OAAO,iBAAiB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/D;IACE,MAAM,EAAE,OAAO,iBAAiB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC,CAAC;AAEN;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,cAAc,CAAC;AAEtD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,eAAe,CAOjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,IAAI,WAAW,CAEvE;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;OAIG;IACH,UAAU,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAExE,4EAA4E;IAC5E,YAAY,CAAC,IAAI,IAAI,CAAC;CACvB"}
1
+ {"version":3,"file":"lb-types.d.ts","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,QAAQ,EACR,SAAS,EAIV,MAAM,mBAAmB,CAAC;AAE3B;;;;;;;GAOG;AACH,MAAM,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE1C;;;;;;;;;GASG;AACH,MAAM,WAAW,KAAK;IACpB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,0EAA0E;AAC1E,MAAM,MAAM,IAAI,GAAG,OAAO,QAAQ,GAAG,OAAO,SAAS,CAAC;AAEtD;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,GAAG,EAAE,GAAG,KAAK,CAAC;AAEvC,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,IAAI,KAAK,CAE3D;AAED,qEAAqE;AACrE,MAAM,MAAM,SAAS,GAAG,GAAG,GAAG,UAAU,CAAC;AAEzC;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,IAAI,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED,wEAAwE;AACxE,MAAM,MAAM,WAAW,GAAG,YAAY,EAAE,CAAC;AAEzC;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED,iEAAiE;AACjE,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AAErD,+DAA+D;AAC/D,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,eAAe,CAOjB;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,eAAe,EACtB,GAAG,EAAE,GAAG,GACP;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,eAAe,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAc1D;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,QAAQ;IACvB;;;;OAIG;IACH,UAAU,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAExE,4EAA4E;IAC5E,YAAY,CAAC,IAAI,IAAI,CAAC;CACvB"}
@@ -1,9 +1,13 @@
1
1
  /// <reference lib="dom" />
2
2
  // The wire vocabulary. Shared by browser and server.
3
- import { LB_RESERVED_PREFIX, } from "./lb-constants.js";
3
+ import { LB_RESERVED_PREFIX, LB_ROW_REQUESTS, URL_COLUMN_PATH, } from "./lb-constants.js";
4
4
  export function isPatch(result) {
5
5
  return !Array.isArray(result);
6
6
  }
7
+ /** Whether a name is one of the requests Loadbare provides. */
8
+ export function isRowRequest(name) {
9
+ return LB_ROW_REQUESTS.includes(name);
10
+ }
7
11
  /**
8
12
  * A query string with some parms set, and the rest as they were. An empty
9
13
  * value takes its parm out, since empty is every parm's default and a
@@ -11,8 +15,8 @@ export function isPatch(result) {
11
15
  *
12
16
  * One rule on both sides of the wire: the hub applies it to the address bar,
13
17
  * and the server to the query string it loads the page at after a request
14
- * returned `QUERY_PARMS_ROW`. The two must agree, or what the page shows
15
- * would differ from what the address bar says.
18
+ * returned `lb-url`. The two must agree, or what the page shows would differ
19
+ * from what the address bar says.
16
20
  */
17
21
  export function withQueryParms(search, parms) {
18
22
  const next = new URLSearchParams(search);
@@ -25,10 +29,39 @@ export function withQueryParms(search, parms) {
25
29
  return next;
26
30
  }
27
31
  /**
28
- * The reserved prefix is the whole of the discriminant. Nothing else tells
29
- * an operation from a declared action, on the wire or anywhere else.
32
+ * A path names a page by its stub, and nothing finer. The bare path resolves
33
+ * to `index`, the same convention a static file server follows.
30
34
  */
31
- export function isOperation(request) {
32
- return request.action.startsWith(LB_RESERVED_PREFIX);
35
+ export function pageNameFor(path) {
36
+ const name = path.replace(/^\/+|\/+$/g, "");
37
+ return name === "" ? "index" : name;
38
+ }
39
+ /**
40
+ * Where a row for `lb-url` leads, from a page and its query parms.
41
+ *
42
+ * A column whose name begins with `lb-` is Loadbare's, and never a query
43
+ * parm; every other column is one. An `lb-path` naming another page enters
44
+ * it with only the parms the row names. Otherwise the named parms are set,
45
+ * or taken out when empty, and the rest are kept.
46
+ *
47
+ * One rule on both sides of the wire: the server loads the page it names,
48
+ * and the hub writes the URL it names. The two must agree, or what the page
49
+ * shows would differ from what the address bar says.
50
+ */
51
+ export function nextLocation(page, parms, row) {
52
+ const named = {};
53
+ for (const [name, value] of Object.entries(row)) {
54
+ if (name.startsWith(LB_RESERVED_PREFIX))
55
+ continue;
56
+ named[name] = value === null || value === undefined ? "" : String(value);
57
+ }
58
+ const path = row[URL_COLUMN_PATH];
59
+ const next = typeof path === "string" ? pageNameFor(path) : page;
60
+ const moved = next !== page;
61
+ return {
62
+ page: next,
63
+ parms: withQueryParms(moved ? new URLSearchParams() : parms, named),
64
+ moved,
65
+ };
33
66
  }
34
67
  //# sourceMappingURL=lb-types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"lb-types.js","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,qDAAqD;AAErD,OAAO,EAIL,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAuC3B,MAAM,UAAU,OAAO,CAAC,MAAkB;IACxC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AAiED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAuB,EACvB,KAA6B;IAE7B,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,EAAE;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;YAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,OAAmB;IAC7C,OAAO,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;AACvD,CAAC","sourcesContent":["/// <reference lib=\"dom\" />\n\n// The wire vocabulary. Shared by browser and server.\n\nimport {\n ACTION_ROW_DELETE,\n ACTION_ROW_INSERT,\n ACTION_ROW_UPDATE,\n LB_RESERVED_PREFIX,\n} from \"./lb-constants.js\";\n\n/**\n * One row: its columns, by name.\n *\n * A value is whatever the server serialized. The hub knows nothing about its\n * type and enforces nothing: it hands each value to the browser untouched,\n * and the browser renders it as it sees fit. What a number, a date or a null\n * should look like is the application's decision, made in the query.\n */\nexport type Row = Record<string, unknown>;\n\n/**\n * Part of a list — see docs/reference/server.md, \"Queries\".\n *\n * Rows named here arrive or are updated, keys in `drop` are gone, and\n * anything unnamed is left alone: its contents, and its place in whatever\n * order the widget is keeping. Add and remove are one result rather than two\n * because the interesting cases are both at once — a row whose sort key\n * changed has to move, a swap is one out and one in — and two messages would\n * paint the intermediate state.\n */\nexport interface Patch {\n rows?: Row[];\n drop?: unknown[];\n}\n\n/**\n * What a list answers with.\n *\n * An array is the entire set and therefore also the order: a row whose key\n * is not in it is gone. A Patch disturbs only what it names.\n *\n * `Array.isArray` tells the two apart, which is why no column name has to be\n * reserved to carry a discriminant. A list answering with an object is a\n * patch, because the declaration already said this name answers with rows.\n */\nexport type ListResult = Row[] | Patch;\n\nexport function isPatch(result: ListResult): result is Patch {\n return !Array.isArray(result);\n}\n\n/**\n * What any one name answers with. Which of the two it is comes from the\n * query's own declaration, never from inspecting the value.\n */\nexport type HubResult = Row | ListResult;\n\n/**\n * Every response on the data channel is the same shape, whether it is a cold\n * start or the narrowest refresh. The hub does not know which case it is in.\n *\n * A name rides as an object key and is labelled by nothing, which is why the\n * response direction never needed a noun for the addressable thing.\n */\nexport type HubData = Record<string, HubResult>;\n\n/**\n * The three operations — docs/reference/data-binding.md. The set is closed.\n *\n * `action` carries the value of `lb-action` verbatim, so the attribute, the\n * wire field and the CRUD key are one vocabulary with no translation step.\n * The scope field is `list` here because all three are list operations: each\n * needs a key, and a key exists only on a live row inside a list.\n */\nexport type LbOperation =\n | {\n action: typeof ACTION_ROW_INSERT;\n list: string;\n values: Record<string, string>;\n }\n | { action: typeof ACTION_ROW_DELETE; list: string; key: string }\n | {\n action: typeof ACTION_ROW_UPDATE;\n list: string;\n key: string;\n values: Record<string, string>;\n };\n\n/**\n * Everything that is not one of the three.\n *\n * The name is the application's and is looked up in the page's declared\n * actions. What keeps this from being an RPC endpoint is that the name must\n * already appear in the page's requests: the browser cannot reach anything the\n * page has not published, and there is no argument list — only where the\n * interaction happened and, where a control has one, its value.\n *\n * The scope field is `list` or `row`, whichever attribute scoped the element\n * the interaction came from, so an action fired from a single-row scope says\n * so. A button carries no value, so the server computes the whole of the new\n * state and the browser never displays a number it has not confirmed. A\n * `<select>` carries one, because the choice is the interaction.\n */\nexport interface DeclaredAction {\n action: string;\n list?: string;\n row?: string;\n key?: string;\n cell?: string;\n value?: string;\n}\n\nexport type HubRequest = LbOperation | DeclaredAction;\n\n/**\n * A query string with some parms set, and the rest as they were. An empty\n * value takes its parm out, since empty is every parm's default and a\n * default is left out of the URL.\n *\n * One rule on both sides of the wire: the hub applies it to the address bar,\n * and the server to the query string it loads the page at after a request\n * returned `QUERY_PARMS_ROW`. The two must agree, or what the page shows\n * would differ from what the address bar says.\n */\nexport function withQueryParms(\n search: URLSearchParams,\n parms: Record<string, string>,\n): URLSearchParams {\n const next = new URLSearchParams(search);\n for (const [name, value] of Object.entries(parms)) {\n if (value === \"\") next.delete(name);\n else next.set(name, value);\n }\n return next;\n}\n\n/**\n * The reserved prefix is the whole of the discriminant. Nothing else tells\n * an operation from a declared action, on the wire or anywhere else.\n */\nexport function isOperation(request: HubRequest): request is LbOperation {\n return request.action.startsWith(LB_RESERVED_PREFIX);\n}\n\n/**\n * The two hooks a list widget may implement, both optional.\n *\n * The hub reconciles every list scope itself, so a widget supplies placement\n * and scaffolding and nothing else. A scope that implements neither is a\n * plain element with a row template inside it, which is why there is no\n * repeater widget.\n *\n * They are methods on an element the hub does not own, so they carry the\n * `lb` prefix that Loadbare reserves for exactly that — see\n * docs/reference/custom-elements.md.\n */\nexport interface ListHost {\n /**\n * Where a row belongs, called with the row detached on its first\n * appearance. Without it a row lands immediately before the template, so\n * rows accumulate in the order they arrive.\n */\n lbPlaceRow?(el: Element, row: Row, template: HTMLTemplateElement): void;\n\n /** Called once after a whole result has landed, for derived scaffolding. */\n lbRowsLanded?(): void;\n}\n"]}
1
+ {"version":3,"file":"lb-types.js","sourceRoot":"","sources":["../../core/lb-types.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAE3B,qDAAqD;AAErD,OAAO,EAGL,kBAAkB,EAClB,eAAe,EACf,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAoC3B,MAAM,UAAU,OAAO,CAAC,MAAkB;IACxC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;AAChC,CAAC;AA2CD,+DAA+D;AAC/D,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAQ,eAAqC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC/D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAuB,EACvB,KAA6B;IAE7B,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,EAAE;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;;YAC/B,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAY,EACZ,KAAsB,EACtB,GAAQ;IAER,MAAM,KAAK,GAA2B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAChD,IAAI,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC;YAAE,SAAS;QAClD,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,IAAI,GAAG,GAAG,CAAC,eAAe,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,MAAM,KAAK,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5B,OAAO;QACL,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC;QACnE,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["/// <reference lib=\"dom\" />\n\n// The wire vocabulary. Shared by browser and server.\n\nimport {\n KIND_ROW,\n KIND_ROWS,\n LB_RESERVED_PREFIX,\n LB_ROW_REQUESTS,\n URL_COLUMN_PATH,\n} from \"./lb-constants.js\";\n\n/**\n * One row: its columns, by name.\n *\n * A value is whatever the server serialized. The hub knows nothing about its\n * type and enforces nothing: it hands each value to the browser untouched,\n * and the browser renders it as it sees fit. What a number, a date or a null\n * should look like is the application's decision, made in the query.\n */\nexport type Row = Record<string, unknown>;\n\n/**\n * Part of a `rows` query's answer — see docs/reference/server.md, \"Queries\".\n *\n * Rows named here are added or updated, keys in `drop` are removed, and\n * anything unnamed is left alone: its contents, and its place in whatever\n * order the widget is keeping. Add and remove are one result rather than two\n * because the interesting cases are both at once — a row whose sort key\n * changed has to move, a swap is one out and one in — and two messages would\n * paint the intermediate state.\n */\nexport interface Patch {\n rows?: Row[];\n drop?: unknown[];\n}\n\n/** A query's kind, declared by the server and carried by every answer. */\nexport type Kind = typeof KIND_ROW | typeof KIND_ROWS;\n\n/**\n * What a `rows` query answers with: all rows, which is also their order, or\n * a patch. `Array.isArray` tells the two apart.\n */\nexport type RowsResult = Row[] | Patch;\n\nexport function isPatch(result: RowsResult): result is Patch {\n return !Array.isArray(result);\n}\n\n/** What any one query answers with, as the application writes it. */\nexport type HubResult = Row | RowsResult;\n\n/**\n * What application code hands the engine: answers by query name. The engine\n * turns each into a response item, adding the kind and key the query\n * declared.\n */\nexport type HubData = Record<string, HubResult>;\n\n/**\n * One query's answer on the wire: its name, its kind, its key's column name,\n * and exactly one of a row, all rows, or a patch. A patch answers a `rows`\n * query only.\n */\nexport interface ResponseItem {\n query: string;\n kind: Kind;\n key: string;\n row?: Row;\n rows?: Row[];\n patch?: Patch;\n}\n\n/** Every response the server sends: a page load and a request alike. */\nexport type HubResponse = ResponseItem[];\n\n/**\n * Every request has one shape. The name picks the handler; the rest is\n * present when the hub found it.\n */\nexport interface HubRequest {\n name: string;\n query?: string;\n key?: string;\n values?: Record<string, string>;\n}\n\n/** The fields a handler receives: the request, less its name. */\nexport type RequestFields = Omit<HubRequest, \"name\">;\n\n/** Whether a name is one of the requests Loadbare provides. */\nexport function isRowRequest(name: string): boolean {\n return (LB_ROW_REQUESTS as readonly string[]).includes(name);\n}\n\n/**\n * A query string with some parms set, and the rest as they were. An empty\n * value takes its parm out, since empty is every parm's default and a\n * default is left out of the URL.\n *\n * One rule on both sides of the wire: the hub applies it to the address bar,\n * and the server to the query string it loads the page at after a request\n * returned `lb-url`. The two must agree, or what the page shows would differ\n * from what the address bar says.\n */\nexport function withQueryParms(\n search: URLSearchParams,\n parms: Record<string, string>,\n): URLSearchParams {\n const next = new URLSearchParams(search);\n for (const [name, value] of Object.entries(parms)) {\n if (value === \"\") next.delete(name);\n else next.set(name, value);\n }\n return next;\n}\n\n/**\n * A path names a page by its stub, and nothing finer. The bare path resolves\n * to `index`, the same convention a static file server follows.\n */\nexport function pageNameFor(path: string): string {\n const name = path.replace(/^\\/+|\\/+$/g, \"\");\n return name === \"\" ? \"index\" : name;\n}\n\n/**\n * Where a row for `lb-url` leads, from a page and its query parms.\n *\n * A column whose name begins with `lb-` is Loadbare's, and never a query\n * parm; every other column is one. An `lb-path` naming another page enters\n * it with only the parms the row names. Otherwise the named parms are set,\n * or taken out when empty, and the rest are kept.\n *\n * One rule on both sides of the wire: the server loads the page it names,\n * and the hub writes the URL it names. The two must agree, or what the page\n * shows would differ from what the address bar says.\n */\nexport function nextLocation(\n page: string,\n parms: URLSearchParams,\n row: Row,\n): { page: string; parms: URLSearchParams; moved: boolean } {\n const named: Record<string, string> = {};\n for (const [name, value] of Object.entries(row)) {\n if (name.startsWith(LB_RESERVED_PREFIX)) continue;\n named[name] = value === null || value === undefined ? \"\" : String(value);\n }\n const path = row[URL_COLUMN_PATH];\n const next = typeof path === \"string\" ? pageNameFor(path) : page;\n const moved = next !== page;\n return {\n page: next,\n parms: withQueryParms(moved ? new URLSearchParams() : parms, named),\n moved,\n };\n}\n\n/**\n * The two hooks a custom element holding rows may implement, both optional.\n *\n * The hub reconciles every row template itself, so a custom element supplies\n * placement and scaffolding and nothing else. They are methods on an element\n * the hub does not own, so they carry the `lb` prefix Loadbare reserves for\n * exactly that — see docs/reference/custom-elements.md.\n */\nexport interface RowsHost {\n /**\n * Where a live row belongs, called with the row detached on its first\n * appearance. Without it a row lands immediately before the template, so\n * rows accumulate in the order they arrive.\n */\n lbPlaceRow?(el: Element, row: Row, template: HTMLTemplateElement): void;\n\n /** Called once after a whole result has landed, for derived scaffolding. */\n lbRowsLanded?(): void;\n}\n"]}
@@ -1,53 +1,63 @@
1
- import { type HubData, type ListResult, type Row } from "../core/lb-types.js";
1
+ import { type ResponseItem, type Row, type RowsResult } from "../core/lb-types.js";
2
+ /** A control's value, whether it is native or a custom element. */
3
+ export interface Control extends Element {
4
+ value: string;
5
+ }
2
6
  /**
3
- * A form control whose state is its `value`: a `<select>`, a `<textarea>`,
4
- * or an `<input>` of any type but checkbox, radio and file. Landing and
5
- * gathering draw the same line, so a value read back from a form is the one
6
- * that landed there.
7
- *
8
- * Told apart by tag name and type rather than by class, so it holds for an
9
- * element from any document.
7
+ * A form-associated custom element with a `value` property. HTML marks one
8
+ * with `static formAssociated = true` on its class, and a control has a value.
9
+ */
10
+ export declare function isFormAssociated(el: Element): boolean;
11
+ /**
12
+ * A control: an `<input>`, `<select>` or `<textarea>`, or a form-associated
13
+ * custom element with a `value` property. Landing and gathering draw the
14
+ * same line, so a value read back is the one that landed there.
10
15
  */
11
- export declare function isValueControl(el: Element): el is HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
16
+ export declare function isControl(el: Element): el is Control;
12
17
  /**
13
- * Root if it matches, then every descendant in root's scope that does.
14
- * Gathering finds cells through here. It does not reach into an absent
15
- * branch, so a form reads back from the places a row lands that are showing.
18
+ * Root if it matches, then every descendant in root's query that does.
19
+ * Gathering finds columns through here. It does not reach into an absent
20
+ * branch, so a live row is read back from the places a row lands that are
21
+ * showing.
16
22
  */
17
23
  export declare function within(root: Element, selector: string): Element[];
18
24
  /**
19
- * Fill one scope from one row.
25
+ * Fill from one row: every `lb-column` and `lb-show` in root's query.
20
26
  *
21
- * The root counts as a cell if it carries one. A `<tr>` holds its cells in
22
- * `<td>` children, but `<option>`'s content model is text, so an option row
23
- * has to be the cell it displays. Requiring a wrapper there would require an
24
- * element HTML does not allow.
27
+ * A live row is its own row, so its root counts when it carries
28
+ * `lb-column`: `<option>`'s content model is text, so an option row has to
29
+ * be the column it displays. An element a `row` lands on is not its own
30
+ * ancestor, so its own `lb-column` reads from the row around it and is left
31
+ * alone here.
32
+ */
33
+ export declare function applyRow(root: Element, row: Row, liveRow?: boolean): void;
34
+ /**
35
+ * The row template: the first `<template>` among the element's descendants,
36
+ * outside any nested `lb-query`. A template holding an absent branch is not a
37
+ * row template: rows land before the row template, so one inside the first
38
+ * live row comes first in document order.
25
39
  */
26
- export declare function applyRow(root: Element, row: Row): void;
40
+ export declare function templateIn(el: Element): HTMLTemplateElement | null;
27
41
  /**
28
- * Land a list result in a list scope.
42
+ * Land rows through a row template.
29
43
  *
30
- * An array is the whole set, so it decides membership and order: every row is
31
- * placed in the order given, and a row whose key did not arrive is gone. A
32
- * patch disturbs only what it names — a row it did not mention keeps its
33
- * contents and its position.
44
+ * All rows decide membership and order: every row is placed in the order
45
+ * given, and a row whose key did not arrive is gone. A patch disturbs only
46
+ * what it names — a row it did not mention keeps its contents and its
47
+ * position.
34
48
  *
35
- * A widget that carries `lbPlaceRow` decides where a row goes, because only
36
- * it knows whether it sorts or groups. Without it a row lands immediately
37
- * before the template, so rows accumulate in the order they arrive and the
38
- * template stays put as the insertion marker.
49
+ * A custom element that carries `lbPlaceRow` decides where a row goes,
50
+ * because only it knows whether it sorts or groups. Without it a row lands
51
+ * immediately before the template, so rows accumulate in the order they
52
+ * arrive and the template stays put as the insertion marker.
39
53
  */
40
- export declare function applyList(scope: Element, result: ListResult): void;
41
- /** Land a whole response. Every result arrives through here. */
42
- export declare function applyData(root: ParentNode, data: HubData): void;
54
+ export declare function applyRows(el: Element, template: HTMLTemplateElement, keyColumn: string, result: RowsResult): void;
43
55
  /**
44
- * Land the query string on every control that writes one of its parms, the
45
- * way a cell lands a column. A parm the URL does not carry lands empty, so a
46
- * control shows what the address bar says after Back as well as after a
47
- * reload: the URL is what is on screen, and nothing else is.
56
+ * Land response items. Every answer arrives through here.
48
57
  *
49
- * Landed after the page's data, so a picker already has the options its
50
- * value selects.
58
+ * `quiet` names queries that may have nowhere to land without a warning: the
59
+ * hub's own `lb-url` lands wherever a chrome or page names it, and nowhere
60
+ * otherwise.
51
61
  */
52
- export declare function applyQueryParms(root: ParentNode, parms: URLSearchParams): void;
62
+ export declare function applyResponse(root: ParentNode, items: ResponseItem[], quiet?: readonly string[]): void;
53
63
  //# sourceMappingURL=lb-apply.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lb-apply.d.ts","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"AAmCA,OAAO,EAEL,KAAK,OAAO,EAEZ,KAAK,UAAU,EACf,KAAK,GAAG,EACT,MAAM,qBAAqB,CAAC;AAW7B;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,EAAE,EAAE,OAAO,GACV,EAAE,IAAI,gBAAgB,GAAG,iBAAiB,GAAG,mBAAmB,CAMlE;AA8DD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAMjE;AAqED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,GAAG,IAAI,CAetD;AA6CD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI,CAgElE;AAED,gEAAgE;AAChE,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAkC/D;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,eAAe,GACrB,IAAI,CAIN"}
1
+ {"version":3,"file":"lb-apply.d.ts","sourceRoot":"","sources":["../../hub/lb-apply.ts"],"names":[],"mappings":"AAkCA,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,GAAG,EAER,KAAK,UAAU,EAChB,MAAM,qBAAqB,CAAC;AAW7B,mEAAmE;AACnE,MAAM,WAAW,OAAQ,SAAQ,OAAO;IACtC,KAAK,EAAE,MAAM,CAAC;CACf;AAiBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAGrD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,EAAE,OAAO,GAAG,EAAE,IAAI,OAAO,CAEpD;AAuDD;;;;;GAKG;AACH,wBAAgB,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,EAAE,CAMjE;AA8DD;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,UAAQ,GAAG,IAAI,CAgBvE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CAKlE;AAcD;;;;;;;;;;;;GAYG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,OAAO,EACX,QAAQ,EAAE,mBAAmB,EAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,UAAU,GACjB,IAAI,CA+DN;AAyBD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,YAAY,EAAE,EACrB,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,IAAI,CAWN"}