@loadbare/widgets 0.10.0 → 0.11.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 (46) hide show
  1. package/README.md +19 -0
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +2 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/lb-mailto.browser.d.ts +2 -0
  7. package/dist/lb-mailto.browser.d.ts.map +1 -0
  8. package/dist/lb-mailto.browser.js +29 -0
  9. package/dist/lb-mailto.browser.js.map +1 -0
  10. package/dist/lb-mailto.html +6 -0
  11. package/dist/lb-tel.browser.d.ts +2 -0
  12. package/dist/lb-tel.browser.d.ts.map +1 -0
  13. package/dist/lb-tel.browser.js +40 -0
  14. package/dist/lb-tel.browser.js.map +1 -0
  15. package/dist/lb-tel.html +6 -0
  16. package/dist-cli/package-root.js +24 -0
  17. package/dist-cli/skills-cli.js +87 -0
  18. package/dist-cli/skills.js +125 -0
  19. package/docs/lb-checkbox.md +2 -2
  20. package/docs/lb-form.md +2 -2
  21. package/docs/lb-input.md +4 -2
  22. package/docs/lb-mailto.md +29 -0
  23. package/docs/lb-master.md +2 -2
  24. package/docs/lb-options.md +2 -0
  25. package/docs/lb-select.md +2 -1
  26. package/docs/lb-table.md +4 -3
  27. package/docs/lb-tel.md +32 -0
  28. package/docs/lb-unknown-page.md +2 -2
  29. package/package.json +12 -4
  30. package/skills/loadbare-widgets/SKILL.md +61 -0
  31. package/skills/loadbare-widgets/references/lb-checkbox.md +63 -0
  32. package/skills/loadbare-widgets/references/lb-confirm.md +44 -0
  33. package/skills/loadbare-widgets/references/lb-date.md +48 -0
  34. package/skills/loadbare-widgets/references/lb-form.md +35 -0
  35. package/skills/loadbare-widgets/references/lb-input.md +77 -0
  36. package/skills/loadbare-widgets/references/lb-insert-dialog.md +73 -0
  37. package/skills/loadbare-widgets/references/lb-mailto.md +29 -0
  38. package/skills/loadbare-widgets/references/lb-master.md +65 -0
  39. package/skills/loadbare-widgets/references/lb-number.md +53 -0
  40. package/skills/loadbare-widgets/references/lb-options.md +113 -0
  41. package/skills/loadbare-widgets/references/lb-picker.md +53 -0
  42. package/skills/loadbare-widgets/references/lb-select.md +70 -0
  43. package/skills/loadbare-widgets/references/lb-table.md +173 -0
  44. package/skills/loadbare-widgets/references/lb-tel.md +32 -0
  45. package/skills/loadbare-widgets/references/lb-unknown-page.md +43 -0
  46. package/docs/temp-feature-request-lb-table.md +0 -130
@@ -0,0 +1,61 @@
1
+ ---
2
+ name: loadbare-widgets
3
+ description: The basic widget set for Loadbare/app, shipped as `@loadbare/widgets`. Covers each widget's parameters, the attributes it reads, and what a change sends; `lb-input`, `lb-select`, `lb-options`, `lb-picker`, `lb-table`, `lb-unknown-page`, `lb-confirm`, `lb-form`, `lb-insert-dialog`, `lb-master`, `lb-checkbox`, `lb-number`, `lb-date`, `lb-tel` and `lb-mailto`. Use whenever a task writes or changes markup using one of these tags, or decides whether a page needs a custom element of its own. The pages, queries and requests the widgets sit in are the loadbare-app skill's.
4
+ license: Apache-2.0
5
+ metadata:
6
+ package: "@loadbare/widgets"
7
+ homepage: https://gitlab.com/kendowns/loadbare
8
+ ---
9
+
10
+ # Working with @loadbare/widgets
11
+
12
+ Every widget is an ordinary custom element for `@loadbare/app`: markup with
13
+ `lb-*` attributes and `exp-*` parameters, landed and gathered by the hub like
14
+ any other element. How pages, queries, requests and custom elements work is
15
+ in the loadbare-app skill. This skill covers only what each widget takes and
16
+ does.
17
+
18
+ Install the package and list it in the application's `src/imports.ts`:
19
+
20
+ ```ts
21
+ export default ["@loadbare/widgets"];
22
+ ```
23
+
24
+ The builder then bundles the definition and script of each widget a page
25
+ uses, and nothing else. The application's own definition of a tag
26
+ overrides the package's.
27
+
28
+ `lb-input`, `lb-select`, `lb-options` and `lb-picker` are controls:
29
+ form-associated custom elements with a `value` property that fire `change`.
30
+ Each carries `lb-column` and `lb-request` itself, the way an `<input>` does.
31
+ Inside a form that sends one request for all its controls, leave
32
+ `lb-request` off.
33
+
34
+ ## Reference material
35
+
36
+ One page per widget. They ship with the package, so no network is needed.
37
+
38
+ | Widget | Is |
39
+ | --- | --- |
40
+ | [`lb-input`](references/lb-input.md) | a control wrapping an `<input>` |
41
+ | [`lb-select`](references/lb-select.md) | a control wrapping a `<select>` whose options the page writes |
42
+ | [`lb-options`](references/lb-options.md) | a control wrapping a `<select>` whose options come from a query |
43
+ | [`lb-picker`](references/lb-picker.md) | `lb-options` with the row template built in |
44
+ | [`lb-table`](references/lb-table.md) | a `<table>` supplying its own scaffolding and a ghost row |
45
+ | [`lb-unknown-page`](references/lb-unknown-page.md) | the chrome's dialog for a URL that names no page |
46
+ | [`lb-confirm`](references/lb-confirm.md) | a button that asks before it sends |
47
+ | [`lb-form`](references/lb-form.md) | a form over one row, which saves per control once the row is on record |
48
+ | [`lb-insert-dialog`](references/lb-insert-dialog.md) | a row entered in a modal dialog, chosen in the picker that opened it |
49
+ | [`lb-master`](references/lb-master.md) | a set, one of its rows, and the buttons that act on the set |
50
+ | [`lb-checkbox`](references/lb-checkbox.md) | a checkbox and its label, as markup to style |
51
+ | [`lb-number`](references/lb-number.md) | a number shown by `Intl.NumberFormat` |
52
+ | [`lb-date`](references/lb-date.md) | a date or time shown by `Intl.DateTimeFormat` |
53
+ | [`lb-tel`](references/lb-tel.md) | a phone number shown as a `tel:` link |
54
+ | [`lb-mailto`](references/lb-mailto.md) | an email address shown as a `mailto:` link |
55
+
56
+ ## The other loadbare skills
57
+
58
+ `npx loadbare-widgets skills install` puts this skill where a coding agent
59
+ finds it. `npx loadbare-app skills install` and
60
+ `npx loadbare-db skills install` do the same for the loadbare-app and
61
+ loadbare-db skills.
@@ -0,0 +1,63 @@
1
+ # `lb-checkbox`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A checkbox and its label as one element, for an application to style. A
6
+ definition only, with no script: the hub treats a native checkbox as a
7
+ control, so the widget adds nothing but the markup.
8
+
9
+ Requires `exp-column` and `exp-label`.
10
+
11
+ ```html
12
+ <div lb-query="people">
13
+ <template>
14
+ <div>
15
+ <lb-checkbox exp-column="active" exp-label="Active" exp-request="lb-row-update"></lb-checkbox>
16
+ </div>
17
+ </template>
18
+ </div>
19
+ ```
20
+
21
+ ## Expansion Attributes
22
+
23
+ | Parameter | Fills |
24
+ | ------------- | ----------------------------------------------- |
25
+ | `exp-column` | the checkbox's `lb-column` |
26
+ | `exp-label` | the label's text |
27
+ | `exp-request` | the checkbox's `lb-request`, none when absent |
28
+
29
+ The column and request go on the checkbox inside, since it is the control,
30
+ so they are expansion attributes here rather than `lb-column` and
31
+ `lb-request` on the tag.
32
+
33
+ ## Why it is not like `lb-input`
34
+
35
+ `lb-input` has a script that makes the tag itself the control, so the page
36
+ writes `lb-column` on the tag. `lb-checkbox` cannot do the same. A value
37
+ that lands before a widget's script has loaded reaches it only as the
38
+ `lb-column-value` stamp, a string, and a checkbox's state is a boolean. A
39
+ script `lb-checkbox` would read the stamp `"false"` as checked, since no
40
+ string is read. The native checkbox has no such gap: the hub sets `checked`
41
+ on it directly.
42
+
43
+ `lb-input` could equally be markup alone; its script is a convention, kept
44
+ for now.
45
+
46
+ ## The control
47
+
48
+ The checkbox is checked when its column is anything but `false` or null, and
49
+ sends `"true"` or `"false"`. See "Checkboxes" in the data-binding reference
50
+ of the loadbare-app skill.
51
+
52
+ ## Styling
53
+
54
+ The definition is a `<label>` holding the `<input type="checkbox">` and a
55
+ `<span>` with the text:
56
+
57
+ ```css
58
+ lb-checkbox label {
59
+ display: inline-flex;
60
+ gap: 0.5em;
61
+ align-items: center;
62
+ }
63
+ ```
@@ -0,0 +1,44 @@
1
+ # `lb-confirm`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A button that asks before it sends. The button opens a dialog holding the
6
+ message the page writes inside the tag, a Cancel button, and a confirm button
7
+ carrying the request.
8
+
9
+ Requires `exp-label` and `exp-request`.
10
+
11
+ ```html
12
+ <template>
13
+ <tr>
14
+ <td lb-column="name"></td>
15
+ <td>
16
+ <lb-confirm exp-label="Delete" exp-request="lb-row-delete">
17
+ Delete <b lb-column="name"></b>?
18
+ </lb-confirm>
19
+ </td>
20
+ </tr>
21
+ </template>
22
+ ```
23
+
24
+ ## Expansion Attributes
25
+
26
+ | Parameter | Fills |
27
+ | ------------- | --------------------------------------------- |
28
+ | `exp-label` | the text of the button that opens the dialog |
29
+ | `exp-request` | the confirm button's `lb-request` |
30
+ | `exp-confirm` | the confirm button's text, `Confirm` when absent |
31
+
32
+ ## The request
33
+
34
+ The request is on the dialog's confirm button, never on the tag, so nothing
35
+ reaches the hub until the user says yes. The dialog sits in the row the tag
36
+ sits in, so the request carries that row's query and key, and the message
37
+ can show the row's columns with `lb-column`.
38
+
39
+ Cancel comes first and takes focus, so Enter on a dialog opened by accident
40
+ sends nothing. The widget closes the dialog when the request succeeds. A refused request leaves it open, with the hub's
41
+ `lb-request-error` on the confirm button.
42
+
43
+ The dialog is found by its place in the tag, not by id, so the tag works in a
44
+ row template, where the hub clones it once per row.
@@ -0,0 +1,48 @@
1
+ # `lb-date`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A date or a time shown by the browser's `Intl.DateTimeFormat`. Not a
6
+ control: write `lb-column` on the tag, and the hub lands the column on it
7
+ and never gathers it.
8
+
9
+ ```html
10
+ <lb-date lb-column="due" exp-date-style="medium"></lb-date>
11
+ ```
12
+
13
+ ## Expansion Attributes
14
+
15
+ Each parameter is one of `Intl.DateTimeFormat`'s options, in kebab-case. A
16
+ parameter not given leaves Intl's default.
17
+
18
+ | Parameter | `Intl.DateTimeFormat` option |
19
+ | -------------------- | ------------------------------------- |
20
+ | `exp-locale` | the locale, the browser's when absent |
21
+ | `exp-date-style` | `dateStyle` |
22
+ | `exp-time-style` | `timeStyle` |
23
+ | `exp-time-zone` | `timeZone` |
24
+ | `exp-time-zone-name` | `timeZoneName` |
25
+ | `exp-hour-cycle` | `hourCycle` |
26
+ | `exp-weekday` | `weekday` |
27
+ | `exp-era` | `era` |
28
+ | `exp-year` | `year` |
29
+ | `exp-month` | `month` |
30
+ | `exp-day` | `day` |
31
+ | `exp-hour` | `hour` |
32
+ | `exp-minute` | `minute` |
33
+ | `exp-second` | `second` |
34
+
35
+ Intl refuses `exp-date-style` or `exp-time-style` beside any of
36
+ `exp-weekday` through `exp-second`.
37
+
38
+ ## The value
39
+
40
+ The widget reads the value as JavaScript's `Date` does. A date alone, as
41
+ `YYYY-MM-DD`, shows as that day in every time zone. A value that is no
42
+ date shows as it arrived. Null shows nothing.
43
+
44
+ ## Styling
45
+
46
+ The definition is a `<time>` whose text is the formatted date and whose
47
+ `datetime` is the value as it arrived. The hub stamps the tag with
48
+ `lb-column-value`, the value as it arrived.
@@ -0,0 +1,35 @@
1
+ # `lb-form`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A `<form>` over one row's controls, in one of two modes the row decides.
6
+
7
+ Requires `exp-id`.
8
+
9
+ ```html
10
+ <section lb-query="account">
11
+ <lb-form exp-id="account-form">
12
+ <lb-input lb-column="name" exp-label="Name" lb-request="lb-row-update"></lb-input>
13
+ </lb-form>
14
+ <button type="submit" form="account-form" lb-request="lb-row-insert">Save new</button>
15
+ </section>
16
+ ```
17
+
18
+ ## Expansion Attributes
19
+
20
+ | Parameter | Fills |
21
+ | --------- | ------------------ |
22
+ | `exp-id` | the form's `id` |
23
+
24
+ ## Two modes
25
+
26
+ A row with a key is on record, and each control saves its own column on
27
+ `change` with `lb-request="lb-row-update"`. A row whose key is empty is a new
28
+ one not yet entered: the hub sends no update for it, so the controls only
29
+ hold what a submit will gather. See "A row not yet entered" in the
30
+ data-binding reference of the loadbare-app skill.
31
+
32
+ A definition only, with no script of its own.
33
+
34
+ A button that acts on the row as a whole, such as one adding it to the set,
35
+ belongs to whatever holds the set, and reaches the form by `form="<id>"`.
@@ -0,0 +1,77 @@
1
+ # `lb-input`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A control wrapping an HTML `<input>`. The hub sets it from a column and
6
+ gathers it back under the same column, as it does a native `<input>`.
7
+
8
+ Requires attributes `lb-column` and `exp-label`.
9
+
10
+ ```html
11
+ <div lb-query="people">
12
+ <template>
13
+ <div>
14
+ <lb-input lb-column="name" exp-label="Name" lb-request="lb-row-update"></lb-input>
15
+ <lb-input lb-column="email" exp-label="Email" exp-readonly></lb-input>
16
+ </div>
17
+ </template>
18
+ </div>
19
+ ```
20
+
21
+ ## Expansion Attributes
22
+
23
+ These are the parameters that control build-time expansion of the final HTML.
24
+
25
+ | Parameter | Fills |
26
+ | -------------- | -------------------------------- |
27
+ | `exp-label` | the visible `<label>` text |
28
+ | `exp-type` | the input's `type`, `text` when absent |
29
+ | `exp-readonly` | the input's `readonly` attribute |
30
+
31
+ Any value on `exp-readonly` makes the input readonly. Leaving the parameter
32
+ off drops the attribute.
33
+
34
+ ## Attributes
35
+
36
+ | Attribute | Names |
37
+ | ------------ | ----------------------------------------- |
38
+ | `lb-column` | the column the input shows and gathers to |
39
+ | `lb-request` | the request a change issues |
40
+
41
+ ## The control
42
+
43
+ `lb-input` is a form-associated custom element. Its `value` property gets and
44
+ sets the value of the `<input>` inside it, and it fires `change` on itself when
45
+ that `<input>` fires `change`. A form reset returns the `<input>` to its
46
+ default. A refusal's message for its column goes to the `<input>`, as HTML's
47
+ own validity.
48
+
49
+ ## Inside a form
50
+
51
+ An `lb-input` inside an `lb-row-insert` or `lb-row-update` form carries no
52
+ `lb-request`. The hub gathers every `lb-column` whose form owner is the form
53
+ on submit and sends one request for all of them, so a widget that also sent
54
+ its own would write the same edit twice.
55
+
56
+ ```html
57
+ <form lb-query="people" lb-request="lb-row-insert">
58
+ <lb-input lb-column="name" exp-label="Name"></lb-input>
59
+ <lb-input lb-column="email" exp-label="Email"></lb-input>
60
+ <button type="submit">Add</button>
61
+ </form>
62
+ ```
63
+
64
+ ## Editing one column
65
+
66
+ With `lb-request`, the `lb-input` commits on `change`. The hub gathers its
67
+ value alone, so `lb-request="lb-row-update"` sends an `lb-row-update` for the
68
+ query and key of the row around it, with `values` holding that one column.
69
+ Any other request name sends that request with the same `query`, `key` and
70
+ `values`.
71
+
72
+ Inside `lb-query="lb-url"`, `lb-request="lb-row-update"` writes the column as a
73
+ query parm, and the hub answers with no round trip.
74
+
75
+ While the request is in flight the hub marks the `lb-input` with
76
+ `lb-request-pending`, and on failure with `lb-request-error`. Both are there
77
+ for a stylesheet to read.
@@ -0,0 +1,73 @@
1
+ # `lb-insert-dialog`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A row entered in a modal dialog, for a set being chosen from elsewhere on the
6
+ page, such as creating an account while a picker chooses one. The page
7
+ writes the controls inside the tag; the dialog supplies the form, Cancel and
8
+ Save.
9
+
10
+ Requires `exp-id`, `exp-title` and `exp-query`.
11
+
12
+ ```html
13
+ <lb-options lb-query="accounts" lb-column="account_id" exp-label="Account">
14
+ <template><option lb-column="name"></option></template>
15
+ </lb-options>
16
+ <button type="button" commandfor="new-account" command="show-modal">New</button>
17
+
18
+ <lb-insert-dialog exp-id="new-account" exp-title="New account" exp-query="accounts">
19
+ <lb-input lb-column="name" exp-label="Name"></lb-input>
20
+ </lb-insert-dialog>
21
+ ```
22
+
23
+ ## Expansion Attributes
24
+
25
+ | Parameter | Fills |
26
+ | ----------- | -------------------------------------------- |
27
+ | `exp-id` | the dialog's `id`, which buttons open |
28
+ | `exp-title` | the dialog's heading |
29
+ | `exp-query` | the `lb-query` of the form, which it inserts into |
30
+ | `exp-save` | the Save button's text, `Save` when absent |
31
+
32
+ ## Where it goes
33
+
34
+ Write it once, outside every row and every form, and open it with HTML's own
35
+ `commandfor` and `command="show-modal"` from as many buttons as need it. A
36
+ form inside another form is dropped by the parser, and `lb-table` joins every
37
+ control in a ghost row to that row's form, so the dialog cannot sit beside
38
+ the control it serves.
39
+
40
+ ## What it does
41
+
42
+ Save is the form's `lb-row-insert`. When it succeeds, the widget chooses the new row in the nearest `lb-options` around
43
+ the button that opened the dialog, fires `change` on it, and closes the
44
+ dialog. The new key comes from the patch the insert answers with, so the
45
+ handler answers with the row it created. A picker that saves its own column
46
+ saves it; one in a ghost row or a new record holds it until Save.
47
+
48
+ A refused insert leaves the dialog open to correct. Cancel and Escape close
49
+ it, and closing resets the form.
50
+
51
+ ## Opening beside the button
52
+
53
+ While the dialog is open, the button that opened it carries
54
+ `insert-dialog-opener` and the widget carries `anchored`, for a stylesheet to
55
+ place the dialog beside the button with CSS anchor positioning:
56
+
57
+ ```css
58
+ [insert-dialog-opener] {
59
+ anchor-name: --insert-dialog-opener;
60
+ }
61
+
62
+ lb-insert-dialog[anchored] .lb-insert-dialog {
63
+ position-anchor: --insert-dialog-opener;
64
+ inset: auto;
65
+ margin: 0;
66
+ position-area: block-end span-inline-end;
67
+ position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
68
+ }
69
+ ```
70
+
71
+ Only one modal is open at a time, so one anchor name serves every dialog.
72
+ Without such a rule, or opened with no button, the dialog stays where the
73
+ browser puts a modal.
@@ -0,0 +1,29 @@
1
+ # `lb-mailto`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ An email address shown as written, as a `mailto:` link. Not a control:
6
+ write `lb-column` on the tag, and the hub lands the column on it and never
7
+ gathers it.
8
+
9
+ ```html
10
+ <lb-mailto lb-column="email"></lb-mailto>
11
+ ```
12
+
13
+ It takes no parameters. To edit the address, use
14
+ `<lb-input exp-type="email">`.
15
+
16
+ ## The value
17
+
18
+ The link's text is the value as it arrived. Its `href` is `mailto:` and the
19
+ address, encoded, so a value carrying `?` or `&` cannot add a subject, a body
20
+ or another recipient to the message.
21
+
22
+ A value with no `@` shows as it arrived, with no `href`. Null shows
23
+ nothing.
24
+
25
+ ## Styling
26
+
27
+ The definition is an `<a>`, with no `href` while there is no address, so
28
+ `lb-mailto a:not([href])` selects a value that is no link. The hub stamps
29
+ the tag with `lb-column-value`, the value as it arrived.
@@ -0,0 +1,65 @@
1
+ # `lb-master`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A set on one side, one of its rows on the other, and the buttons that act on
6
+ the set. A definition only, with no script of its own: it is built from
7
+ [`lb-form`](./lb-form.md) and [`lb-confirm`](./lb-confirm.md).
8
+
9
+ Requires `exp-row`.
10
+
11
+ ```html
12
+ <lb-master exp-row="account">
13
+ <template lb-exp-template="picker">
14
+ <div lb-query="lb-url">
15
+ <lb-picker lb-query="accounts" lb-column="acct" lb-request="lb-row-update"
16
+ exp-label="Account" exp-column="name"></lb-picker>
17
+ </div>
18
+ </template>
19
+ <lb-input lb-column="name" exp-label="Name" lb-request="lb-row-update"></lb-input>
20
+ <template lb-exp-template="delete-message">
21
+ Delete <b lb-column="name"></b>?
22
+ </template>
23
+ </lb-master>
24
+ ```
25
+
26
+ ## Expansion Attributes
27
+
28
+ | Parameter | Fills |
29
+ | -------------- | ---------------------------------------------- |
30
+ | `exp-row` | the `lb-query` of the row the form shows |
31
+ | `exp-form-id` | the form's `id`, `master-form` when absent |
32
+
33
+ | Template | Fills |
34
+ | ------------------------------------------- | ----------------------------- |
35
+ | `<template lb-exp-template="picker">` | the side that chooses the row |
36
+ | `<template lb-exp-template="delete-message">` | the question Delete asks |
37
+
38
+ ## The buttons
39
+
40
+ | Button | Shows | Does |
41
+ | -------- | ----------------- | --------------------------------------------- |
42
+ | New | A row on record | Sends `new`, a request the page declares, and pushes a history entry |
43
+ | Copy | A row on record | Sends `copy`, a request the page declares |
44
+ | Delete | A row on record | Asks, then sends `lb-row-delete` |
45
+ | Save new | A new row | Submits the form as `lb-row-insert`, and pushes a history entry |
46
+ | Cancel | A new row | Resets the form |
47
+
48
+ Each carries `data-mode`, `on-record` or `new`, and the stylesheet shows each
49
+ only in its mode. A new row is one whose key is empty, a row not yet entered
50
+ (see that section in the data-binding reference of the loadbare-app skill).
51
+
52
+ Which row shows is a query parm, and only the page knows its name, so New is
53
+ a request the page declares. Its handler empties the parm, and the row
54
+ query answers a row with an empty key:
55
+
56
+ ```ts
57
+ handlers: {
58
+ new: { run: async () => url({ acct: "" }), refresh: [] },
59
+ },
60
+ ```
61
+
62
+ Choosing the picker's blank does the same.
63
+
64
+ Copy goes to the server rather than filling the form, because a copy is a new
65
+ row in the set, and only the server can bring its children along.
@@ -0,0 +1,53 @@
1
+ # `lb-number`
2
+
3
+ > Status: a barebones starter. Iterative use will drive improvements.
4
+
5
+ A number shown by the browser's `Intl.NumberFormat`. Not a control: write
6
+ `lb-column` on the tag, and the hub lands the column on it and never gathers
7
+ it.
8
+
9
+ ```html
10
+ <lb-number lb-column="balance" exp-style="currency" exp-currency="USD"></lb-number>
11
+ ```
12
+
13
+ ## Expansion Attributes
14
+
15
+ Each parameter is one of `Intl.NumberFormat`'s options, in kebab-case. A
16
+ parameter not given leaves Intl's default.
17
+
18
+ | Parameter | `Intl.NumberFormat` option |
19
+ | -------------------------------- | -------------------------------------- |
20
+ | `exp-locale` | the locale, the browser's when absent |
21
+ | `exp-style` | `style` |
22
+ | `exp-currency` | `currency` |
23
+ | `exp-currency-display` | `currencyDisplay` |
24
+ | `exp-currency-sign` | `currencySign` |
25
+ | `exp-unit` | `unit` |
26
+ | `exp-unit-display` | `unitDisplay` |
27
+ | `exp-notation` | `notation` |
28
+ | `exp-compact-display` | `compactDisplay` |
29
+ | `exp-sign-display` | `signDisplay` |
30
+ | `exp-minimum-integer-digits` | `minimumIntegerDigits` |
31
+ | `exp-minimum-fraction-digits` | `minimumFractionDigits` |
32
+ | `exp-maximum-fraction-digits` | `maximumFractionDigits` |
33
+ | `exp-minimum-significant-digits` | `minimumSignificantDigits` |
34
+ | `exp-maximum-significant-digits` | `maximumSignificantDigits` |
35
+
36
+ ## The value
37
+
38
+ The widget formats the value as the string it arrived as, so a decimal the
39
+ query sends as a string keeps every digit. A value that is no number shows
40
+ as it arrived. Null shows nothing.
41
+
42
+ ## Styling
43
+
44
+ The definition is a `<data>` whose text is the formatted number and whose
45
+ `value` is the number as it arrived. The hub stamps the tag with
46
+ `lb-column-value`, the number as it arrived, so a stylesheet selects on the
47
+ value itself:
48
+
49
+ ```css
50
+ lb-number[lb-column-value^="-"] {
51
+ color: var(--negative);
52
+ }
53
+ ```
@@ -0,0 +1,113 @@
1
+ # `lb-options`
2
+
3
+ A control wrapping an HTML `<select>`, with the `<option>`s coming from a
4
+ query.
5
+
6
+ Apply the `lb-query` attribute to name the query, `lb-column` to name the
7
+ column the choice shows and gathers to, and `lb-request` to name the request a
8
+ change issues. Write a `<template>` inside the tag, and apply `lb-column` to
9
+ the `<option>` itself — an `<option>` holds text, not elements. For options
10
+ in groups, write a group template holding an `<optgroup>`.
11
+
12
+ Provide `exp-label`.
13
+
14
+ ```html
15
+ <lb-options
16
+ lb-query="statuses"
17
+ lb-column="status_id"
18
+ exp-label="Status"
19
+ lb-request="setStatus"
20
+ >
21
+ <template lb-group>
22
+ <optgroup>
23
+ <template><option lb-column="label"></option></template>
24
+ </optgroup>
25
+ </template>
26
+ </lb-options>
27
+ ```
28
+
29
+ ## Status
30
+
31
+ Barebones starter to prove out the publish/consume chain and identify necessary
32
+ improvements through iterative use.
33
+
34
+ ## Parameters
35
+
36
+ | Parameter | Fills |
37
+ | ----------- | -------------------------- |
38
+ | `exp-label` | the visible `<label>` text |
39
+ | `exp-size` | the `<select>`'s `size`, an open list of that many rows rather than a drop-down |
40
+
41
+ ## Attributes
42
+
43
+ | Attribute | On | Names |
44
+ | ------------ | ------------------ | ------------------------------------------ |
45
+ | `lb-query` | the element itself | the query whose rows become options |
46
+ | `lb-column` | the element itself | the column the choice shows and gathers to |
47
+ | `lb-request` | the element itself | the request a change issues |
48
+ | `lb-group` | a template holding an `<optgroup>` | a group of options |
49
+ | `lb-column` | the `<option>` | the column the option shows |
50
+
51
+ The server declares the query's key. The widget copies each option's
52
+ `lb-key-value` to its `value`.
53
+
54
+ ## Grouping
55
+
56
+ The hub makes one `<optgroup>` per run of the query's order's leading term.
57
+ An `<optgroup>` takes its label from an attribute, which landing does not
58
+ set, so the widget labels each from the `lb-group-value` the hub stamps on
59
+ it: the value the group breaks on.
60
+
61
+ That value is often a number kept for sorting, such as a category's display
62
+ order, and a number is no label. For a label from a column of the group's
63
+ first row, write a heading option marked `data-group-label` in the
64
+ `<optgroup>`, filled like any group heading:
65
+
66
+ ```html
67
+ <template lb-group>
68
+ <optgroup>
69
+ <option data-group-label hidden disabled lb-column="category"></option>
70
+ <template><option lb-column="account_name"></option></template>
71
+ </optgroup>
72
+ </template>
73
+ ```
74
+
75
+ The widget takes the heading option's text as the label. Mark it `hidden`
76
+ and `disabled` so it is never a choice.
77
+
78
+ ## The control
79
+
80
+ `lb-options` is a form-associated custom element. Its `value` property gets
81
+ and sets the value of the `<select>` inside it, and it fires `change` on itself
82
+ when that `<select>` fires `change`. A form reset selects the first option.
83
+ A refusal's message for its column goes to the `<select>`, as HTML's own
84
+ validity.
85
+
86
+ The hub reads the element's own `lb-column` from the row around it, and lands
87
+ the rows of its `lb-query` inside it. A value set before the option it names
88
+ has landed selects that option when the rows land.
89
+
90
+ ## Choosing
91
+
92
+ With `lb-request`, the `lb-options` commits on `change`. The hub gathers its
93
+ value alone, the key of the chosen row, and sends the request with the `query`
94
+ and `key` of the row around it. Declare that request on the server, or name
95
+ `lb-row-update`.
96
+
97
+ Without `lb-request`, a change commits nothing, and the form or live row around
98
+ the `lb-options` gathers its value.
99
+
100
+ Inside `lb-query="lb-url"`, `lb-request="lb-row-update"` writes the chosen key
101
+ as a query parm, and the hub answers with no round trip.
102
+
103
+ While the request is in flight the hub marks the `lb-options` with
104
+ `lb-request-pending`, and on failure with `lb-request-error`. Both are there
105
+ for a stylesheet to read.
106
+
107
+ ## Styling an empty list
108
+
109
+ `lb-options` carries `lb-query-row-count` with the number of options showing,
110
+ for a stylesheet to read.
111
+
112
+ For the case where every row is one option and only the column names vary,
113
+ see [`lb-picker`](./lb-picker.md).