staffa 0.19.0 → 0.22.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.
- package/README.md +12 -2
- package/dist/components/autocomplete.d.ts +30 -1
- package/dist/components/autocomplete.js +63 -12
- package/dist/components/button.d.ts +24 -13
- package/dist/components/button.js +34 -20
- package/dist/components/dialog.d.ts +3 -2
- package/dist/components/dialog.js +33 -6
- package/dist/components/field.d.ts +38 -0
- package/dist/components/field.js +65 -0
- package/dist/components/textarea.d.ts +16 -3
- package/dist/components/textarea.js +36 -24
- package/dist/components/textline.d.ts +5 -2
- package/dist/components/textline.js +19 -14
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/staffa.esm.js +1 -1
- package/package.json +2 -2
- package/skill/AutocompleteOptions.md +15 -1
- package/skill/ButtonOptions.md +6 -4
- package/skill/IconButtonOptions.md +10 -7
- package/skill/InsetOptions.md +23 -0
- package/skill/SKILL.md +28 -2
- package/skill/TextareaOptions.md +4 -1
- package/skill/autocomplete.md +4 -0
- package/skill/dialog.md +3 -2
- package/skill/iconButton.md +3 -1
- package/skill/matchWords.md +17 -0
- package/skill/textarea.md +8 -0
- package/skill/textline.md +3 -0
- package/src/components/autocomplete.ts +78 -12
- package/src/components/button.ts +61 -31
- package/src/components/dialog.ts +33 -6
- package/src/components/field.ts +87 -0
- package/src/components/textarea.ts +38 -21
- package/src/components/textline.ts +15 -10
- package/src/index.ts +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
|
-
import { applyControlAttrs, drawField } from "./field.js";
|
|
2
|
+
import { applyControlAttrs, drawField, drawInsets } from "./field.js";
|
|
3
3
|
A.insertGlobalCss({
|
|
4
4
|
"textarea.s-input": "resize:vertical min-height:3em line-height:1.45",
|
|
5
5
|
"textarea.s-input.s-autoGrow": "resize:none min-height:2.5em overflow-y:hidden",
|
|
@@ -12,36 +12,48 @@ A.insertGlobalCss({
|
|
|
12
12
|
* ```ts
|
|
13
13
|
* const $user = A.proxy({bio: ""});
|
|
14
14
|
* S.textarea({ label: "Bio", bind: A.ref($user, "bio") });
|
|
15
|
+
*
|
|
16
|
+
* // A chat box: the send button sits in the bottom-right corner, inside the field.
|
|
17
|
+
* const $chat = A.proxy({text: ""});
|
|
18
|
+
* S.textarea({
|
|
19
|
+
* placeholder: "Message…",
|
|
20
|
+
* bind: A.ref($chat, "text"),
|
|
21
|
+
* suffix: () => S.iconButton({ icon: send, tooltip: "Send", click: () => post($chat.text) }),
|
|
22
|
+
* });
|
|
15
23
|
* ```
|
|
16
24
|
*/
|
|
17
25
|
export function textarea(opts = {}) {
|
|
18
26
|
const grow = opts.autoGrow !== false;
|
|
19
27
|
drawField(opts, (id, isInvalid) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
// Insets ride the bottom edge here: on a growing box that keeps a send
|
|
29
|
+
// button beside the caret rather than floating it mid-paragraph.
|
|
30
|
+
drawInsets(opts, true, () => {
|
|
31
|
+
const el = A("textarea.s-input", opts.inputAttrs, () => {
|
|
32
|
+
if (grow) {
|
|
33
|
+
A(".s-autoGrow");
|
|
34
|
+
A("input=", (e) => {
|
|
35
|
+
fitToContent(e.currentTarget);
|
|
36
|
+
if (opts.input)
|
|
37
|
+
opts.input(e);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
A("rows=", opts.rows ?? 4);
|
|
42
|
+
A("resize:", opts.resize ?? (opts.suffix ? "none" : "vertical"));
|
|
25
43
|
if (opts.input)
|
|
26
|
-
opts.input
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (opts.
|
|
33
|
-
A("
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
A("value=", opts.value);
|
|
39
|
-
if (opts.change)
|
|
40
|
-
A("change=", opts.change);
|
|
41
|
-
applyControlAttrs(opts, id, isInvalid, opts.bind);
|
|
44
|
+
A("input=", opts.input);
|
|
45
|
+
}
|
|
46
|
+
if (opts.placeholder != null)
|
|
47
|
+
A("placeholder=", opts.placeholder);
|
|
48
|
+
if (opts.value != null && !opts.bind)
|
|
49
|
+
A("value=", opts.value);
|
|
50
|
+
if (opts.change)
|
|
51
|
+
A("change=", opts.change);
|
|
52
|
+
applyControlAttrs(opts, id, isInvalid, opts.bind);
|
|
53
|
+
});
|
|
54
|
+
if (grow)
|
|
55
|
+
requestAnimationFrame(() => fitToContent(el));
|
|
42
56
|
});
|
|
43
|
-
if (grow)
|
|
44
|
-
requestAnimationFrame(() => fitToContent(el));
|
|
45
57
|
});
|
|
46
58
|
}
|
|
47
59
|
function fitToContent(el) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Bindable } from "../core.js";
|
|
2
|
-
import { type FieldOptions } from "./field.js";
|
|
2
|
+
import { type FieldOptions, type InsetOptions } from "./field.js";
|
|
3
3
|
/**
|
|
4
4
|
* The `<input>` types {@link textline} supports. Deliberately excludes types
|
|
5
5
|
* that need their own widget (`checkbox`, `radio`, `color`, `range`, `file`,
|
|
@@ -7,7 +7,7 @@ import { type FieldOptions } from "./field.js";
|
|
|
7
7
|
*/
|
|
8
8
|
export type TextlineType = "text" | "password" | "email" | "number" | "tel" | "url" | "search" | "date" | "time" | "datetime-local" | "month" | "week";
|
|
9
9
|
/** Options for {@link textline}. */
|
|
10
|
-
export interface TextlineOptions extends FieldOptions {
|
|
10
|
+
export interface TextlineOptions extends FieldOptions, InsetOptions {
|
|
11
11
|
/** Input type. Defaults to `"text"`. */
|
|
12
12
|
type?: TextlineType;
|
|
13
13
|
/** Placeholder text. */
|
|
@@ -32,6 +32,9 @@ export interface TextlineOptions extends FieldOptions {
|
|
|
32
32
|
* ```ts
|
|
33
33
|
* const $user = A.proxy({email: "test@example.com"});
|
|
34
34
|
* S.textline({ label: "Email", type: "email", required: true, bind: A.ref($user, "email") });
|
|
35
|
+
*
|
|
36
|
+
* // Content inside the field: a glyph against its left edge, a button against its right.
|
|
37
|
+
* S.textline({ placeholder: "Search…", prefix: search, suffix: () => S.iconButton({ icon: x, tooltip: "Clear" }) });
|
|
35
38
|
* ```
|
|
36
39
|
*/
|
|
37
40
|
export declare function textline(opts?: TextlineOptions): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import A from "aberdeen";
|
|
2
|
-
import { applyControlAttrs, drawField } from "./field.js";
|
|
2
|
+
import { applyControlAttrs, drawField, drawInsets } from "./field.js";
|
|
3
3
|
/**
|
|
4
4
|
* A single-line text input — text, passwords, numbers, email, dates and the other
|
|
5
5
|
* line-oriented `<input>` types. Renders inside the standard {@link drawField}
|
|
@@ -9,23 +9,28 @@ import { applyControlAttrs, drawField } from "./field.js";
|
|
|
9
9
|
* ```ts
|
|
10
10
|
* const $user = A.proxy({email: "test@example.com"});
|
|
11
11
|
* S.textline({ label: "Email", type: "email", required: true, bind: A.ref($user, "email") });
|
|
12
|
+
*
|
|
13
|
+
* // Content inside the field: a glyph against its left edge, a button against its right.
|
|
14
|
+
* S.textline({ placeholder: "Search…", prefix: search, suffix: () => S.iconButton({ icon: x, tooltip: "Clear" }) });
|
|
12
15
|
* ```
|
|
13
16
|
*/
|
|
14
17
|
export function textline(opts = {}) {
|
|
15
18
|
drawField(opts, (id, isInvalid) => {
|
|
16
|
-
|
|
17
|
-
A("
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
drawInsets(opts, false, () => {
|
|
20
|
+
A("input.s-input", opts.inputAttrs, () => {
|
|
21
|
+
A("type=", opts.type ?? "text");
|
|
22
|
+
if (opts.placeholder != null)
|
|
23
|
+
A("placeholder=", opts.placeholder);
|
|
24
|
+
if (opts.autocomplete != null)
|
|
25
|
+
A("autocomplete=", opts.autocomplete);
|
|
26
|
+
if (opts.value != null && !opts.bind)
|
|
27
|
+
A("value=", opts.value);
|
|
28
|
+
if (opts.input)
|
|
29
|
+
A("input=", opts.input);
|
|
30
|
+
if (opts.change)
|
|
31
|
+
A("change=", opts.change);
|
|
32
|
+
applyControlAttrs(opts, id, isInvalid, opts.bind);
|
|
33
|
+
});
|
|
29
34
|
});
|
|
30
35
|
});
|
|
31
36
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
export { setDarkMode, getDarkMode } from "./theme.js";
|
|
33
33
|
export { formatKey, bindKey } from "./keys.js";
|
|
34
34
|
export { showKeyHelp, setKeyHelp } from "./components/keyhelp.js";
|
|
35
|
-
export { autocomplete, type AutocompleteOptions, type AutocompleteOptionInput } from "./components/autocomplete.js";
|
|
35
|
+
export { autocomplete, matchWords, type AutocompleteOptions, type AutocompleteOptionInput } from "./components/autocomplete.js";
|
|
36
36
|
export { box, type BoxOptions } from "./components/box.js";
|
|
37
37
|
export { button, iconButton, type ButtonOptions, type IconButtonOptions } from "./components/button.js";
|
|
38
38
|
export { buttonChooser, type ButtonChooserOptions } from "./components/buttonChooser.js";
|
|
@@ -49,5 +49,5 @@ export { textarea, type TextareaOptions } from "./components/textarea.js";
|
|
|
49
49
|
export { textline, type TextlineOptions, type TextlineType } from "./components/textline.js";
|
|
50
50
|
export { toast, type ToastOptions } from "./components/toast.js";
|
|
51
51
|
export { addTooltip, type TooltipOptions } from "./components/tooltip.js";
|
|
52
|
-
export type { FieldOptions } from "./components/field.js";
|
|
52
|
+
export type { FieldOptions, InsetOptions } from "./components/field.js";
|
|
53
53
|
export type { ContentOptions, Bindable, Slot, Attributes } from "./core.js";
|
package/dist/index.js
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
export { setDarkMode, getDarkMode } from "./theme.js";
|
|
35
35
|
export { formatKey, bindKey } from "./keys.js";
|
|
36
36
|
export { showKeyHelp, setKeyHelp } from "./components/keyhelp.js";
|
|
37
|
-
export { autocomplete } from "./components/autocomplete.js";
|
|
37
|
+
export { autocomplete, matchWords } from "./components/autocomplete.js";
|
|
38
38
|
export { box } from "./components/box.js";
|
|
39
39
|
export { button, iconButton } from "./components/button.js";
|
|
40
40
|
export { buttonChooser } from "./components/buttonChooser.js";
|