@loadbare/app 0.18.1 → 0.18.2

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.
@@ -42,3 +42,166 @@ See [`chrome.html`](./chrome.md) for the link, [The Express
42
42
  server](./server.md) for the route, and
43
43
  [`loadbare-app-build`](./builder.md#running-the-builder) for `--minify`.
44
44
  </content>
45
+
46
+ ## Selecting what the hub stamps
47
+
48
+ The hub tells a stylesheet everything it knows through attributes, so an
49
+ application styles state with selectors and writes no script for it. Each
50
+ stamp is an `lb-` attribute the hub writes; never write one in markup.
51
+
52
+ ### A value
53
+
54
+ Every element a column lands on carries the value as `lb-column-value`,
55
+ exactly as the query sent it, and loses it when the value is null. Select
56
+ on the column and the value:
57
+
58
+ ```css
59
+ [lb-column="status"][lb-column-value="locked"] { opacity: 0.5; }
60
+ [lb-column="balance"][lb-column-value^="-"] { color: var(--negative); }
61
+ [lb-column="note"]:not([lb-column-value]) { display: none; }
62
+ ```
63
+
64
+ A widget that formats its value, such as `lb-number`, keeps the raw value
65
+ in the stamp, so the selector reads the number and not its text. See
66
+ [Where a column lands](./data-binding.md#where-a-column-lands).
67
+
68
+ ### A row
69
+
70
+ | Select | For |
71
+ |----------------------|-------------------------------------------------|
72
+ | `[lb-row-live]` | Every live row of a list |
73
+ | `[lb-row-selected]` | A row its `lb-select` checkbox ticks |
74
+ | `[lb-row-editing]` | The row a pointed form is editing |
75
+ | `[lb-key-value="…"]` | One row, by its key |
76
+ | `[hidden]` | A row a filter hides; the browser hides it |
77
+
78
+ An element a `row` query lands on carries `lb-key-value` while the query has
79
+ a row, and loses it when the query answers `null`:
80
+
81
+ ```css
82
+ [lb-query="member"]:not([lb-key-value]) .member-missing { display: revert; }
83
+ ```
84
+
85
+ Select live rows with `[lb-row-live]`, never with `[lb-key-value]`: a `row`
86
+ landed inside a list, such as a total in a table's foot, carries a key and
87
+ is not one of the list's rows.
88
+
89
+ ```css
90
+ [lb-row-selected] { background: var(--selected); }
91
+ [lb-row-editing] { outline: 2px solid var(--accent); }
92
+ ```
93
+
94
+ See [Rows](./data-binding.md#rows), [Selecting rows](./data-binding.md#selecting-rows)
95
+ and [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form).
96
+
97
+ ### A group
98
+
99
+ Each top-level element of a group carries `lb-group-live`, the column it
100
+ breaks on as `lb-group-column`, and its value there as `lb-group-value`:
101
+
102
+ ```css
103
+ [lb-group-column="category"][lb-group-value="Income"] { color: var(--income); }
104
+ ```
105
+
106
+ See [Groups](./data-binding.md#groups).
107
+
108
+ ### What just happened to a row
109
+
110
+ The hub stamps what its last landing did, so a stylesheet animates with
111
+ nothing else:
112
+
113
+ | Select | For |
114
+ |--------------------------------|------------------------------------------------|
115
+ | `[lb-row-created]` | A row that arrived |
116
+ | `[lb-row-changed]` | A row whose values changed |
117
+ | `[lb-row-moved]` | A row whose values changed and now stands elsewhere; it carries `lb-row-changed` too |
118
+ | `[lb-row-requested]` | Any of the three, done by this page's request, as `created`, `changed` or `moved` |
119
+ | `[lb-row-leaving]`, `[lb-group-leaving]` | A row or group on its way out; the hub removes it when its animations end |
120
+
121
+ ```css
122
+ [lb-row-created] { animation: arrive 200ms; }
123
+ [lb-row-requested="changed"] { animation: flash 600ms; }
124
+ [lb-row-leaving] { animation: depart 200ms forwards; }
125
+ ```
126
+
127
+ A row stamped again plays its animation again. See
128
+ [What happened to a row](./data-binding.md#what-happened-to-a-row).
129
+
130
+ ### How many rows show
131
+
132
+ An element carrying `lb-query` and a row template carries
133
+ `lb-query-row-count`, the number of live rows showing. A row a filter hides
134
+ is not counted.
135
+
136
+ ```css
137
+ .roster-empty { display: none; }
138
+ [lb-query-row-count="0"] .roster-empty { display: revert; }
139
+ ```
140
+
141
+ See [Counting rows](./data-binding.md#counting-rows).
142
+
143
+ ### A request
144
+
145
+ | Select | For |
146
+ |------------------------|---------------------------------------------------------|
147
+ | `[lb-request-pending]` | The element that committed, while its round trip is out; `aria-busy="true"` rides with it |
148
+ | `[lb-request-error]` | The element whose round trip failed, until it commits again |
149
+ | `[lb-request-refused]` | The element whose request the handler refused, holding the message, empty when there is none |
150
+ | `:invalid` | A control a refusal named a column for |
151
+
152
+ The hub ignores a commit on a pending element, so the stylesheet only has to
153
+ show it:
154
+
155
+ ```css
156
+ [lb-request-pending] { cursor: progress; opacity: 0.6; }
157
+ [lb-request-error] { outline: 2px solid var(--error); }
158
+ [lb-request-refused]:not([lb-request-refused=""])::after {
159
+ content: attr(lb-request-refused);
160
+ }
161
+ ```
162
+
163
+ See [Request state](./data-binding.md#request-state) and
164
+ [Refusals](./data-binding.md#refusals).
165
+
166
+ ### A form pointed at a row
167
+
168
+ A pointed form's `lb-key-value` says what it is doing:
169
+
170
+ | Select | The form is |
171
+ |------------------------------|--------------------|
172
+ | `form[lb-key-value]:not([lb-key-value=""])` | Editing a row |
173
+ | `form[lb-key-value=""]` | Entering a new row |
174
+ | `form:not([lb-key-value])` | Not in use |
175
+
176
+ ```css
177
+ form[lb-key-value=""] .save-existing,
178
+ form:not([lb-key-value=""]) .save-new { display: none; }
179
+ ```
180
+
181
+ See [Editing a row in one form](./data-binding.md#editing-a-row-in-one-form).
182
+
183
+ ### The user's choices
184
+
185
+ An order or a filter the user chose is a column of `lb-choices`, so the
186
+ element showing it carries it as `lb-column-value`. Style anything else by
187
+ it with `:has()`:
188
+
189
+ ```css
190
+ table:has([lb-column="accounts_order"][lb-column-value="-balance"])
191
+ th.balance::after { content: "▼"; }
192
+ ```
193
+
194
+ See [Choices](./data-binding.md#choices).
195
+
196
+ ### Content shown by condition
197
+
198
+ An element `lb-show` turns off is moved into a `<template>`, so no selector
199
+ reaches it and nothing about it needs styling. The `<template>` keeps its
200
+ place, so `:nth-child()` counts it; prefer `:nth-child(… of …)` or a class
201
+ over position. See [Where an absent element is](./data-binding.md#where-an-absent-element-is).
202
+
203
+ ### The first load
204
+
205
+ Write `hidden` on the chrome's `<body>`, and the hub removes it once the
206
+ first page has landed. See
207
+ [Preventing the first-load blink](./chrome.md#preventing-the-first-load-blink).
@@ -95,6 +95,10 @@ not `lb-row-live`, so a `row` shown inside another query, such as a total in
95
95
  a table's foot, is not one of that query's rows. Select live rows with
96
96
  `[lb-row-live]`, never with `[lb-key-value]`.
97
97
 
98
+ A `row` query answering `null` found no row. The hub lands every column the
99
+ element names as null and removes its `lb-key-value`; under a row template,
100
+ the live row leaves.
101
+
98
102
  Write `lb-column` on each element that shows a column. The element reads
99
103
  from its nearest ancestor row: the live row it is in, or the element a
100
104
  `row` landed on. A nested `lb-query` begins a new query, and what is inside
@@ -139,7 +143,10 @@ from its element file, and renders `lb-column-value` itself; see
139
143
  A file input receives nothing, and the hub reports it to the console.
140
144
 
141
145
  The hub hands every value to the browser as the server sent it. What a
142
- number, a date or a null looks like is decided in the query.
146
+ number, a date or a null looks like is decided in the query, or by a custom
147
+ element that formats it, such as
148
+ [`lb-number` and `lb-date`](./widgets.md#lb-number-and-lb-date). Send a
149
+ column the user sorts or filters raw, and format it in the element.
143
150
 
144
151
  ### Checkboxes
145
152
 
@@ -96,7 +96,7 @@ export const queries: Queries = {
96
96
 
97
97
  | Declared with | Answers with |
98
98
  |----------------------------|-------------------------------------------|
99
- | `row(key, run)` | One row, an object |
99
+ | `row(key, run)` | One row, an object, or `null` for none |
100
100
  | `rows(key, run, options)` | All its rows, an array of objects |
101
101
 
102
102
  `options` are a `rows` query's order and column types. `order` is the
@@ -317,6 +317,7 @@ queries:
317
317
  | Answer | States |
318
318
  |--------------------------|---------------------------------------------|
319
319
  | `{ ... }` | The row of a `row` query |
320
+ | `null` | A `row` query found no row |
320
321
  | `[...]` | All rows of a `rows` query, and their order |
321
322
  | `patch({ rows: [...] })` | These rows arrive or change; the rest stand |
322
323
  | `patch({ drop: [...] })` | These keys are gone; the rest stand |
@@ -1,8 +1,8 @@
1
1
  # The Basic Widget Library
2
2
 
3
- Eleven widgets: `lb-input`, `lb-select`, `lb-options`, `lb-picker`,
3
+ Thirteen widgets: `lb-input`, `lb-select`, `lb-options`, `lb-picker`,
4
4
  `lb-table`, `lb-unknown-page`, `lb-confirm`, `lb-form`, `lb-insert-dialog`,
5
- `lb-master` and `lb-checkbox`. Every one of them is an ordinary custom element, written
5
+ `lb-master`, `lb-checkbox`, `lb-number` and `lb-date`. Every one of them is an ordinary custom element, written
6
6
  against the contracts in [Custom Elements](./custom-elements.md#html) for its
7
7
  definition and [Custom Elements](./custom-elements.md#code) for its class.
8
8
 
@@ -258,6 +258,28 @@ checked. The hub sets a native checkbox's `checked` directly.
258
258
  | `exp-label` | The label's text |
259
259
  | `exp-request` | The checkbox's `lb-request`, none when absent |
260
260
 
261
+ ## `lb-number` and `lb-date`
262
+
263
+ A number shown by the browser's `Intl.NumberFormat`, and a date or time
264
+ shown by `Intl.DateTimeFormat`. Neither is a control: `lb-column` goes on
265
+ the tag, and the widget renders the `lb-column-value` the hub stamps; see
266
+ [Receiving a value](./custom-elements.md#receiving-a-value).
267
+
268
+ ```html
269
+ <lb-number lb-column="balance" exp-style="currency" exp-currency="USD"></lb-number>
270
+ <lb-date lb-column="due" exp-date-style="medium"></lb-date>
271
+ ```
272
+
273
+ Each parameter is one of Intl's options in kebab-case, as `exp-currency-sign`
274
+ for `currencySign`, plus `exp-locale`. A value that is no number or date
275
+ shows as it arrived, and a date alone, `YYYY-MM-DD`, shows as that day in
276
+ every time zone. The stamp keeps the raw value, so a stylesheet selects on
277
+ it:
278
+
279
+ ```css
280
+ lb-number[lb-column-value^="-"] { color: var(--negative); }
281
+ ```
282
+
261
283
  ## `lb-unknown-page`
262
284
 
263
285
  The chrome's dialog for a URL that names no page, as one tag: