@syware/jlib 0.5.1 → 0.7.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/dist/all.js +11 -4
- package/dist/atoms/jl-app-icon.css_raw.js +3 -0
- package/dist/atoms/jl-app-icon.d.ts +34 -0
- package/dist/atoms/jl-app-icon.js +86 -0
- package/dist/atoms/jl-avatar.js +1 -1
- package/dist/atoms/jl-badge.js +9 -2
- package/dist/atoms/jl-button.d.ts +5 -0
- package/dist/atoms/jl-button.js +5 -2
- package/dist/atoms/jl-chip.js +3 -2
- package/dist/atoms/jl-input.js +5 -4
- package/dist/atoms/jl-link.js +2 -2
- package/dist/atoms/jl-rating.js +4 -5
- package/dist/atoms/jl-select.css_raw.js +1 -1
- package/dist/atoms/jl-select.d.ts +3 -2
- package/dist/atoms/jl-select.js +6 -5
- package/dist/atoms/jl-spinner.js +2 -2
- package/dist/base/jl-form-control.js +2 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +10 -3
- package/dist/lib/app-icon.d.ts +8 -0
- package/dist/lib/app-icon.js +37 -0
- package/dist/lib/dom.d.ts +2 -0
- package/dist/lib/dom.js +3 -1
- package/dist/lib/download.d.ts +10 -0
- package/dist/lib/download.js +62 -0
- package/dist/lib/icons.d.ts +4 -0
- package/dist/lib/icons.js +7 -4
- package/dist/lib/input-list.d.ts +12 -0
- package/dist/lib/input-list.js +14 -0
- package/dist/lib/internals.d.ts +5 -0
- package/dist/lib/internals.js +18 -0
- package/dist/lib/palette.js +6 -0
- package/dist/lib/resize.d.ts +2 -0
- package/dist/lib/resize.js +10 -0
- package/dist/lib/table.d.ts +6 -1
- package/dist/lib/table.js +16 -1
- package/dist/lib/text.d.ts +12 -0
- package/dist/lib/text.js +16 -1
- package/dist/lib/texts.d.ts +97 -0
- package/dist/lib/texts.js +102 -0
- package/dist/lib/time.d.ts +5 -3
- package/dist/lib/time.js +23 -15
- package/dist/lib/tree.d.ts +10 -1
- package/dist/lib/tree.js +37 -3
- package/dist/lib/trigger.js +1 -1
- package/dist/molecules/jl-account-button.css_raw.js +1 -1
- package/dist/molecules/jl-account-button.d.ts +8 -1
- package/dist/molecules/jl-account-button.js +9 -2
- package/dist/molecules/jl-alert.js +3 -2
- package/dist/molecules/jl-breadcrumb.js +3 -3
- package/dist/molecules/jl-calendar.js +5 -5
- package/dist/molecules/jl-chip-group.js +3 -3
- package/dist/molecules/jl-code-block.css_raw.js +1 -1
- package/dist/molecules/jl-code-block.d.ts +5 -0
- package/dist/molecules/jl-code-block.js +5 -2
- package/dist/molecules/jl-combobox.js +6 -7
- package/dist/molecules/jl-copy-button.js +5 -4
- package/dist/molecules/jl-date-picker.js +7 -8
- package/dist/molecules/jl-empty.js +2 -2
- package/dist/molecules/jl-facts.css_raw.js +3 -0
- package/dist/molecules/jl-facts.d.ts +35 -0
- package/dist/molecules/jl-facts.js +64 -0
- package/dist/molecules/jl-file-drop.d.ts +5 -0
- package/dist/molecules/jl-file-drop.js +18 -15
- package/dist/molecules/jl-input-list.css_raw.js +3 -0
- package/dist/molecules/jl-input-list.d.ts +79 -0
- package/dist/molecules/jl-input-list.js +177 -0
- package/dist/molecules/jl-list-item.js +1 -1
- package/dist/molecules/jl-load-more.css_raw.js +3 -0
- package/dist/molecules/jl-load-more.d.ts +41 -0
- package/dist/molecules/jl-load-more.js +62 -0
- package/dist/molecules/jl-load-state.d.ts +4 -1
- package/dist/molecules/jl-load-state.js +20 -12
- package/dist/molecules/jl-menu.js +1 -1
- package/dist/molecules/jl-number-input.js +5 -5
- package/dist/molecules/jl-pagination.js +5 -5
- package/dist/molecules/jl-radio-group.js +2 -2
- package/dist/molecules/jl-search-button.js +5 -5
- package/dist/molecules/jl-search.js +5 -5
- package/dist/molecules/jl-segmented.js +3 -2
- package/dist/molecules/jl-steps.css_raw.js +1 -1
- package/dist/molecules/jl-steps.d.ts +2 -0
- package/dist/molecules/jl-steps.js +30 -14
- package/dist/molecules/jl-tabs.js +3 -2
- package/dist/molecules/jl-tag-input.js +3 -3
- package/dist/molecules/jl-timeline.js +1 -1
- package/dist/molecules/jl-toast.css_raw.js +1 -1
- package/dist/molecules/jl-toast.d.ts +13 -1
- package/dist/molecules/jl-toast.js +23 -3
- package/dist/molecules/jl-tooltip.d.ts +4 -1
- package/dist/molecules/jl-tooltip.js +27 -15
- package/dist/organisms/jl-command-palette.css_raw.js +1 -1
- package/dist/organisms/jl-command-palette.d.ts +14 -0
- package/dist/organisms/jl-command-palette.js +40 -10
- package/dist/organisms/jl-confirm.d.ts +2 -1
- package/dist/organisms/jl-confirm.js +18 -12
- package/dist/organisms/jl-dialog.js +2 -1
- package/dist/organisms/jl-drawer.js +2 -1
- package/dist/organisms/jl-flow.js +13 -13
- package/dist/organisms/jl-navbar.js +6 -6
- package/dist/organisms/jl-side-nav.css_raw.js +1 -1
- package/dist/organisms/jl-side-nav.d.ts +33 -1
- package/dist/organisms/jl-side-nav.js +71 -14
- package/dist/organisms/jl-tab-bar.js +3 -3
- package/dist/organisms/jl-table.css_raw.js +1 -1
- package/dist/organisms/jl-table.d.ts +9 -0
- package/dist/organisms/jl-table.js +36 -6
- package/dist/organisms/jl-toaster.css_raw.js +1 -1
- package/dist/organisms/jl-toaster.d.ts +9 -1
- package/dist/organisms/jl-toaster.js +148 -7
- package/dist/organisms/jl-tree.css_raw.js +1 -1
- package/dist/organisms/jl-tree.d.ts +71 -4
- package/dist/organisms/jl-tree.js +303 -40
- package/dist/styles/tokens.css_raw.js +1 -1
- package/dist/templates/jl-app-shell.css_raw.js +1 -1
- package/dist/templates/jl-app-shell.d.ts +16 -1
- package/dist/templates/jl-app-shell.js +42 -3
- package/dist/templates/jl-auth-layout.css_raw.js +3 -0
- package/dist/templates/jl-auth-layout.d.ts +35 -0
- package/dist/templates/jl-auth-layout.js +139 -0
- package/dist/templates/jl-page.css_raw.js +1 -1
- package/dist/templates/jl-page.js +3 -3
- package/dist/templates/jl-split-view.css_raw.js +1 -1
- package/dist/templates/jl-split-view.d.ts +21 -1
- package/dist/templates/jl-split-view.js +37 -4
- package/dist/tokens.css +2 -0
- package/dist/types/jl-app-icon.types.d.ts +5 -0
- package/dist/types/jl-command-palette.types.d.ts +7 -0
- package/dist/types/jl-facts.types.d.ts +17 -0
- package/dist/types/jl-side-nav.types.d.ts +2 -0
- package/dist/types/jl-split-view.types.d.ts +2 -0
- package/dist/types/jl-steps.types.d.ts +2 -0
- package/dist/types/jl-table.types.d.ts +9 -2
- package/dist/types/jl-toaster.types.d.ts +42 -1
- package/dist/types/jl-tree.types.d.ts +26 -0
- package/dist/types/texts.types.d.ts +5 -0
- package/package.json +3 -3
|
@@ -3,8 +3,9 @@ import { JlFormControl } from "../base/jl-form-control.js";
|
|
|
3
3
|
import { oneOf } from "../lib/attributes.js";
|
|
4
4
|
import { registerIcons } from "../lib/icons.js";
|
|
5
5
|
import { CONTROL_SIZES } from "../lib/options.js";
|
|
6
|
-
import {
|
|
6
|
+
import { jlText } from "../lib/texts.js";
|
|
7
7
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
8
|
+
import { setOrRemove } from "../lib/dom.js";
|
|
8
9
|
import { clamp, parseNumber, stepValue } from "../lib/numeric.js";
|
|
9
10
|
import jl_number_input_default from "./jl-number-input.css_raw.js";
|
|
10
11
|
import { css } from "@jadis/core";
|
|
@@ -18,7 +19,6 @@ registerIcons({
|
|
|
18
19
|
var DEFAULT_STEP = 1;
|
|
19
20
|
var PAGE_STEPS = 10;
|
|
20
21
|
var ICON_SIZE = 14;
|
|
21
|
-
var VALUE_MISSING = "Please fill in this field.";
|
|
22
22
|
var positiveStep = (value) => {
|
|
23
23
|
const parsed = parseNumber(value);
|
|
24
24
|
return parsed === null || parsed <= 0 ? DEFAULT_STEP : parsed;
|
|
@@ -89,7 +89,7 @@ var JlNumberInput = class extends JlFormControl {
|
|
|
89
89
|
class: "action step down",
|
|
90
90
|
type: "button",
|
|
91
91
|
tabIndex: -1,
|
|
92
|
-
"aria-label": "
|
|
92
|
+
"aria-label": jlText("decrease"),
|
|
93
93
|
children: /* @__PURE__ */ jsx(JlIcon, {
|
|
94
94
|
name: "minus",
|
|
95
95
|
size: ICON_SIZE
|
|
@@ -106,7 +106,7 @@ var JlNumberInput = class extends JlFormControl {
|
|
|
106
106
|
class: "action step up",
|
|
107
107
|
type: "button",
|
|
108
108
|
tabIndex: -1,
|
|
109
|
-
"aria-label": "
|
|
109
|
+
"aria-label": jlText("increase"),
|
|
110
110
|
children: /* @__PURE__ */ jsx(JlIcon, {
|
|
111
111
|
name: "plus",
|
|
112
112
|
size: ICON_SIZE
|
|
@@ -213,7 +213,7 @@ var JlNumberInput = class extends JlFormControl {
|
|
|
213
213
|
this.internals.setValidity({});
|
|
214
214
|
return;
|
|
215
215
|
}
|
|
216
|
-
this.internals.setValidity({ valueMissing: true },
|
|
216
|
+
this.internals.setValidity({ valueMissing: true }, jlText("fillField"), this._refs.native);
|
|
217
217
|
}
|
|
218
218
|
};
|
|
219
219
|
JlNumberInput.register();
|
|
@@ -3,6 +3,7 @@ import { JlElement } from "../base/jl-element.js";
|
|
|
3
3
|
import { clampedNumber, oneOf } from "../lib/attributes.js";
|
|
4
4
|
import { registerIcons } from "../lib/icons.js";
|
|
5
5
|
import { CONTROL_SIZES } from "../lib/options.js";
|
|
6
|
+
import { jlText } from "../lib/texts.js";
|
|
6
7
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
7
8
|
import { clampPage, pageItems } from "../lib/pagination.js";
|
|
8
9
|
import jl_pagination_default from "./jl-pagination.css_raw.js";
|
|
@@ -19,7 +20,6 @@ var ICON_SIZES = {
|
|
|
19
20
|
md: 16,
|
|
20
21
|
sm: 14
|
|
21
22
|
};
|
|
22
|
-
var DEFAULT_LABEL = "Pagination";
|
|
23
23
|
var MAX_PAGES = Number.MAX_SAFE_INTEGER;
|
|
24
24
|
var MAX_NEIGHBOURS = 5;
|
|
25
25
|
var STEP_BACK = -1;
|
|
@@ -61,8 +61,8 @@ var JlPagination = class extends JlElement {
|
|
|
61
61
|
parse: oneOf(CONTROL_SIZES, "md")
|
|
62
62
|
});
|
|
63
63
|
/** The navigation's name for screen readers, when a page has more than one. */
|
|
64
|
-
label = this.useChange(
|
|
65
|
-
this._refs.nav.setAttribute("aria-label", value ||
|
|
64
|
+
label = this.useChange(jlText("pagination"), (value) => {
|
|
65
|
+
this._refs.nav.setAttribute("aria-label", value || jlText("pagination"));
|
|
66
66
|
}, { attribute: "label" });
|
|
67
67
|
_refs = this.useRefs((ref) => ({
|
|
68
68
|
list: ref(".pages"),
|
|
@@ -80,7 +80,7 @@ var JlPagination = class extends JlElement {
|
|
|
80
80
|
/* @__PURE__ */ jsx("button", {
|
|
81
81
|
type: "button",
|
|
82
82
|
class: "button previous",
|
|
83
|
-
"aria-label": "
|
|
83
|
+
"aria-label": jlText("previousPage"),
|
|
84
84
|
children: /* @__PURE__ */ jsx(JlIcon, { name: "chevron-left" })
|
|
85
85
|
}),
|
|
86
86
|
/* @__PURE__ */ jsx("ol", { class: "pages" }),
|
|
@@ -91,7 +91,7 @@ var JlPagination = class extends JlElement {
|
|
|
91
91
|
/* @__PURE__ */ jsx("button", {
|
|
92
92
|
type: "button",
|
|
93
93
|
class: "button next",
|
|
94
|
-
"aria-label": "
|
|
94
|
+
"aria-label": jlText("nextPage"),
|
|
95
95
|
children: /* @__PURE__ */ jsx(JlIcon, { name: "chevron-right" })
|
|
96
96
|
})
|
|
97
97
|
]
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BASE_STYLES } from "../styles/shared.js";
|
|
2
2
|
import { JlFormControl } from "../base/jl-form-control.js";
|
|
3
3
|
import { jsonOf, oneOf } from "../lib/attributes.js";
|
|
4
|
+
import { jlText } from "../lib/texts.js";
|
|
4
5
|
import { rovingIndex } from "../lib/roving-index.js";
|
|
5
6
|
import jl_radio_group_default from "./jl-radio-group.css_raw.js";
|
|
6
7
|
import { css } from "@jadis/core";
|
|
@@ -10,7 +11,6 @@ var RADIO_GROUP_ORIENTATIONS = ["vertical", "horizontal"];
|
|
|
10
11
|
var RADIO_GROUP_VARIANTS = ["plain", "cards"];
|
|
11
12
|
var NO_VALUE = "";
|
|
12
13
|
var OPTION_SELECTOR = "[role=\"radio\"]";
|
|
13
|
-
var VALUE_MISSING = "Please select one of these options.";
|
|
14
14
|
/** The keys that move the choice, as with native radios: both arrow pairs whatever the orientation. */
|
|
15
15
|
var MOVES = /* @__PURE__ */ new Map([
|
|
16
16
|
["ArrowDown", "next"],
|
|
@@ -195,7 +195,7 @@ var JlRadioGroup = class extends JlFormControl {
|
|
|
195
195
|
this.internals.setValidity({});
|
|
196
196
|
return;
|
|
197
197
|
}
|
|
198
|
-
this.internals.setValidity({ valueMissing: true },
|
|
198
|
+
this.internals.setValidity({ valueMissing: true }, jlText("selectOption"), this.radios()[0] ?? this._refs.group);
|
|
199
199
|
}
|
|
200
200
|
};
|
|
201
201
|
JlRadioGroup.register();
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { BASE_STYLES } from "../styles/shared.js";
|
|
2
2
|
import { JlElement } from "../base/jl-element.js";
|
|
3
3
|
import { registerIcons } from "../lib/icons.js";
|
|
4
|
-
import {
|
|
4
|
+
import { jlText } from "../lib/texts.js";
|
|
5
5
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
6
|
+
import { setOrRemove } from "../lib/dom.js";
|
|
6
7
|
import { JlKbd } from "../atoms/jl-kbd.js";
|
|
7
8
|
import { parseShortcut, shortcutAria } from "../lib/key-shortcut.js";
|
|
8
9
|
import jl_search_button_default from "./jl-search-button.css_raw.js";
|
|
@@ -11,7 +12,6 @@ import { Search } from "lucide";
|
|
|
11
12
|
import { jsx, jsxs } from "@jadis/core/jsx-runtime";
|
|
12
13
|
// src/molecules/jl-search-button.tsx
|
|
13
14
|
registerIcons({ search: Search });
|
|
14
|
-
var DEFAULT_LABEL = "Search";
|
|
15
15
|
var DEFAULT_HOTKEY = "mod+k";
|
|
16
16
|
var NO_HOTKEY = "none";
|
|
17
17
|
var ICON_SIZE = 15;
|
|
@@ -26,14 +26,14 @@ var JlSearchButton = class extends JlElement {
|
|
|
26
26
|
static selector = "jl-search-button";
|
|
27
27
|
events = this.useEvents();
|
|
28
28
|
/** The text, and the button's name: "Search". */
|
|
29
|
-
label = this.useChange(
|
|
29
|
+
label = this.useChange(jlText("search"), () => this.renderLabel(), { attribute: "label" });
|
|
30
30
|
/** The keys that open the palette, as `jl-kbd` writes them: `mod+k`; `none` for no keys. */
|
|
31
31
|
hotkey = this.useChange(DEFAULT_HOTKEY, () => this.renderHotkey(), { attribute: "hotkey" });
|
|
32
32
|
/** The icon alone, the label as its tooltip. */
|
|
33
33
|
compact = this.useChange(false, (value) => this.reflect("compact", value), { attribute: "compact" });
|
|
34
34
|
_refs = this.useRefs((ref) => ({
|
|
35
35
|
button: ref("button"),
|
|
36
|
-
keys: ref(
|
|
36
|
+
keys: ref(JlKbd),
|
|
37
37
|
text: ref(".text")
|
|
38
38
|
}));
|
|
39
39
|
focus(options) {
|
|
@@ -63,7 +63,7 @@ var JlSearchButton = class extends JlElement {
|
|
|
63
63
|
this.on(this._refs.button, "click", () => this.events.emit("press"));
|
|
64
64
|
}
|
|
65
65
|
renderLabel() {
|
|
66
|
-
const label = this.label.get() ||
|
|
66
|
+
const label = this.label.get() || jlText("search");
|
|
67
67
|
this._refs.text.textContent = label;
|
|
68
68
|
this._refs.button.setAttribute("aria-label", label);
|
|
69
69
|
this._refs.button.title = label;
|
|
@@ -3,8 +3,9 @@ import { JlFormControl } from "../base/jl-form-control.js";
|
|
|
3
3
|
import { oneOf } from "../lib/attributes.js";
|
|
4
4
|
import { registerIcons } from "../lib/icons.js";
|
|
5
5
|
import { CONTROL_SIZES } from "../lib/options.js";
|
|
6
|
-
import {
|
|
6
|
+
import { jlText } from "../lib/texts.js";
|
|
7
7
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
8
|
+
import { setOrRemove } from "../lib/dom.js";
|
|
8
9
|
import { JlSpinner } from "../atoms/jl-spinner.js";
|
|
9
10
|
import { hasCommandModifier, matchesShortcut, parseShortcut, shortcutAria, shortcutLabels } from "../lib/key-shortcut.js";
|
|
10
11
|
import jl_search_default from "./jl-search.css_raw.js";
|
|
@@ -19,7 +20,6 @@ registerIcons({
|
|
|
19
20
|
var DEFAULT_DEBOUNCE_MS = 250;
|
|
20
21
|
var ICON_SIZE = 16;
|
|
21
22
|
var ACTION_ICON_SIZE = 14;
|
|
22
|
-
var DEFAULT_LABEL = "Search";
|
|
23
23
|
var MAC_PATTERN = /Mac|iPhone|iPad|iPod/;
|
|
24
24
|
var TYPING_TARGETS = "input, textarea, select, [contenteditable]";
|
|
25
25
|
var isMac = () => MAC_PATTERN.test(navigator.userAgent);
|
|
@@ -38,7 +38,7 @@ var JlSearch = class extends JlFormControl {
|
|
|
38
38
|
value = this.useChange("", (value) => this.renderValue(value), { attribute: "value" });
|
|
39
39
|
placeholder = this.useChange("", (value) => setOrRemove(this._refs.native, "placeholder", value), { attribute: "placeholder" });
|
|
40
40
|
/** The field's name for screen readers; "Search" when nothing else names it. */
|
|
41
|
-
label = this.useChange("", (value) => this._refs.native.setAttribute("aria-label", value ||
|
|
41
|
+
label = this.useChange("", (value) => this._refs.native.setAttribute("aria-label", value || jlText("search")), { attribute: "label" });
|
|
42
42
|
/** How long typing must pause, in milliseconds, before `search` fires. */
|
|
43
43
|
debounce = this.useChange(DEFAULT_DEBOUNCE_MS, () => void 0, { attribute: "debounce" });
|
|
44
44
|
/** Keys that focus the field from anywhere: "/" or "mod+k" (⌘ on a Mac, Ctrl elsewhere). */
|
|
@@ -68,7 +68,7 @@ var JlSearch = class extends JlFormControl {
|
|
|
68
68
|
icon: ref(".icon"),
|
|
69
69
|
keys: ref(".keys"),
|
|
70
70
|
native: ref("input"),
|
|
71
|
-
spinner: ref(
|
|
71
|
+
spinner: ref(JlSpinner)
|
|
72
72
|
}));
|
|
73
73
|
focus(options) {
|
|
74
74
|
this._refs.native.focus(options);
|
|
@@ -108,7 +108,7 @@ var JlSearch = class extends JlFormControl {
|
|
|
108
108
|
/* @__PURE__ */ jsx("button", {
|
|
109
109
|
class: "action clear",
|
|
110
110
|
type: "button",
|
|
111
|
-
"aria-label": "
|
|
111
|
+
"aria-label": jlText("clearSearch"),
|
|
112
112
|
tabIndex: -1,
|
|
113
113
|
hidden: true,
|
|
114
114
|
children: /* @__PURE__ */ jsx(JlIcon, {
|
|
@@ -2,10 +2,11 @@ import { BASE_STYLES } from "../styles/shared.js";
|
|
|
2
2
|
import { JlFormControl } from "../base/jl-form-control.js";
|
|
3
3
|
import { jsonOf, oneOf } from "../lib/attributes.js";
|
|
4
4
|
import { CONTROL_SIZES } from "../lib/options.js";
|
|
5
|
-
import { setOrRemove } from "../lib/dom.js";
|
|
6
5
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
6
|
+
import { setOrRemove } from "../lib/dom.js";
|
|
7
7
|
import { firstIndex, lastIndex, stepIndex } from "../lib/roving.js";
|
|
8
8
|
import { moveIndicator } from "../lib/indicator.js";
|
|
9
|
+
import { watchSizes } from "../lib/resize.js";
|
|
9
10
|
import jl_segmented_default from "./jl-segmented.css_raw.js";
|
|
10
11
|
import { css } from "@jadis/core";
|
|
11
12
|
import { jsx, jsxs } from "@jadis/core/jsx-runtime";
|
|
@@ -55,7 +56,7 @@ var JlSegmented = class extends JlFormControl {
|
|
|
55
56
|
/** The group's name for screen readers, when no visible label names it. */
|
|
56
57
|
label = this.useChange("", (value) => setOrRemove(this._refs.group, "aria-label", value), { attribute: "label" });
|
|
57
58
|
_state = { disabledByForm: false };
|
|
58
|
-
_resize =
|
|
59
|
+
_resize = watchSizes(() => this.placeThumb());
|
|
59
60
|
_refs = this.useRefs((ref) => ({
|
|
60
61
|
group: ref(".group"),
|
|
61
62
|
thumb: ref(".thumb")
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/molecules/jl-steps.css?raw
|
|
2
|
-
var jl_steps_default = ":host {\n display: block;\n container-type: inline-size;\n --marker: 28px;\n}\n\nol {\n display: flex;\n padding: 0;\n list-style: none;\n}\n\n.step {\n display: flex;\n flex: 1;\n min-width: 0;\n}\n\n.step:last-child {\n flex: none;\n}\n\n.head {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n padding: 0;\n border: none;\n border-radius: var(--jl-radius-xs);\n background: none;\n text-align: start;\n}\n\nbutton.head {\n cursor: pointer;\n}\n\n.marker {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: var(--marker);\n height: var(--marker);\n border: 1px solid var(--jl-line-strong);\n border-radius: 50%;\n background: var(--jl-surface);\n color: var(--jl-muted);\n font-size: var(--jl-font-sm);\n font-weight: 650;\n font-variant-numeric: tabular-nums;\n}\n\n.text {\n display: grid;\n gap: 2px;\n min-width: 0;\n padding-top: 4px;\n}\n\n.label {\n color: var(--jl-muted);\n font-size: var(--jl-font-md);\n font-weight: 600;\n line-height: 20px;\n}\n\n.description {\n color: var(--jl-muted);\n font-size: var(--jl-font-xs);\n line-height: 1.45;\n}\n\n.step[data-status=\"done\"] .marker {\n border-color: var(--jl-accent-line);\n background: var(--jl-accent-soft);\n color: var(--jl-accent);\n}\n\n.step[data-status=\"done\"] .label {\n color: var(--jl-text);\n}\n\n.step[data-status=\"current\"] .marker {\n border-color: var(--jl-accent);\n background: var(--jl-accent);\n color: var(--jl-on-accent);\n box-shadow: 0 0 0 4px var(--jl-accent-soft);\n}\n\n.step[data-status=\"current\"] .label {\n color: var(--jl-accent);\n font-weight: 700;\n}\n\nbutton.head:hover .label {\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n\n.line {\n flex: 1;\n min-width: 24px;\n height: 1px;\n /* Further from the label before it than from the next marker: a label reads as its own step's. */\n margin: calc(var(--marker) / 2) 12px 0 20px;\n background: var(--jl-line-strong);\n}\n\n.step[data-status=\"done\"] .line {\n background: var(--jl-accent);\n}\n\n.step:last-child .line {\n display: none;\n}\n\n/* Vertical: the markers in a column joined by a rule, the text beside them. */\n:host([orientation=\"vertical\"]) ol {\n flex-direction: column;\n}\n\n:host([orientation=\"vertical\"]) .step {\n position: relative;\n flex: none;\n padding-bottom: 24px;\n}\n\n:host([orientation=\"vertical\"]) .step:last-child {\n padding-bottom: 0;\n}\n\n:host([orientation=\"vertical\"]) .line {\n position: absolute;\n top: calc(var(--marker) + 4px);\n bottom: 4px;\n left: calc(var(--marker) / 2 - 0.5px);\n width: 1px;\n height: auto;\n min-width: 0;\n margin: 0;\n}\n\n/* Narrow, the horizontal steps keep their markers and only the current step's text. */\n@container (width < 560px) {\n /* Out of sight, still read: the same rules as .sr-only. */\n :host(:not([orientation=\"vertical\"])) .step:not([data-status=\"current\"]) .text {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n\n :host(:not([orientation=\"vertical\"])) .description {\n display: none;\n }\n\n :host(:not([orientation=\"vertical\"])) .line {\n min-width: 8px;\n margin: calc(var(--marker) / 2) 8px 0;\n }\n\n /* The current step takes three shares of the room, the others one, never less than their marker and line: the\n label never runs into the next step, and takes an ellipsis only when there is no room at all. */\n :host(:not([orientation=\"vertical\"])) .step:not([data-status=\"current\"]) {\n min-width: min-content;\n }\n\n :host(:not([orientation=\"vertical\"])) .step[data-status=\"current\"] {\n flex: 3 1 0;\n }\n\n :host(:not([orientation=\"vertical\"])) .step[data-status=\"current\"] .label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n :host(:not([orientation=\"vertical\"])) .step[data-status=\"current\"] .line {\n min-width: 24px;\n margin-left: 16px;\n }\n}\n";
|
|
2
|
+
var jl_steps_default = ":host {\n display: block;\n container-type: inline-size;\n --marker: 28px;\n}\n\nol {\n display: flex;\n padding: 0;\n list-style: none;\n}\n\n.step {\n display: flex;\n flex: 1;\n min-width: 0;\n}\n\n.step:last-child {\n flex: none;\n}\n\n.head {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n min-width: 0;\n padding: 0;\n border: none;\n border-radius: var(--jl-radius-xs);\n background: none;\n text-align: start;\n}\n\nbutton.head {\n cursor: pointer;\n}\n\n.marker {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: var(--marker);\n height: var(--marker);\n border: 1px solid var(--jl-line-strong);\n border-radius: 50%;\n background: var(--jl-surface);\n color: var(--jl-muted);\n font-size: var(--jl-font-sm);\n font-weight: 650;\n font-variant-numeric: tabular-nums;\n}\n\n.text {\n display: grid;\n gap: 2px;\n min-width: 0;\n padding-top: 4px;\n}\n\n.label {\n color: var(--jl-muted);\n font-size: var(--jl-font-md);\n font-weight: 600;\n line-height: 20px;\n}\n\n.description {\n color: var(--jl-muted);\n font-size: var(--jl-font-xs);\n line-height: 1.45;\n}\n\n.step[data-status=\"done\"] .marker {\n border-color: var(--jl-accent-line);\n background: var(--jl-accent-soft);\n color: var(--jl-accent);\n}\n\n.step[data-status=\"done\"] .label {\n color: var(--jl-text);\n}\n\n.step[data-status=\"current\"] .marker {\n border-color: var(--jl-accent);\n background: var(--jl-accent);\n color: var(--jl-on-accent);\n box-shadow: 0 0 0 4px var(--jl-accent-soft);\n}\n\n.step[data-status=\"current\"] .label {\n color: var(--jl-accent);\n font-weight: 700;\n}\n\n.step[data-failed] .marker {\n border-color: color-mix(in srgb, var(--jl-danger) 40%, var(--jl-line));\n background: var(--jl-danger-soft);\n color: var(--jl-danger);\n box-shadow: none;\n}\n\n.step[data-failed] .label {\n color: var(--jl-danger);\n}\n\nbutton.head:hover .label {\n text-decoration: underline;\n text-underline-offset: 3px;\n}\n\n.line {\n flex: 1;\n min-width: 24px;\n height: 1px;\n /* Further from the label before it than from the next marker: a label reads as its own step's. */\n margin: calc(var(--marker) / 2) 12px 0 20px;\n background: var(--jl-line-strong);\n}\n\n.step[data-status=\"done\"] .line {\n background: var(--jl-accent);\n}\n\n.step:last-child .line {\n display: none;\n}\n\n/* Vertical: the markers in a column joined by a rule, the text beside them. */\n:host([orientation=\"vertical\"]) ol {\n flex-direction: column;\n}\n\n:host([orientation=\"vertical\"]) .step {\n position: relative;\n flex: none;\n padding-bottom: 24px;\n}\n\n:host([orientation=\"vertical\"]) .step:last-child {\n padding-bottom: 0;\n}\n\n:host([orientation=\"vertical\"]) .line {\n position: absolute;\n top: calc(var(--marker) + 4px);\n bottom: 4px;\n left: calc(var(--marker) / 2 - 0.5px);\n width: 1px;\n height: auto;\n min-width: 0;\n margin: 0;\n}\n\n/* Narrow, the horizontal steps keep their markers and only the current step's text. */\n@container (width < 560px) {\n /* Out of sight, still read: the same rules as .sr-only. */\n :host(:not([orientation=\"vertical\"])) .step:not([data-status=\"current\"]) .text {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n }\n\n :host(:not([orientation=\"vertical\"])) .description {\n display: none;\n }\n\n :host(:not([orientation=\"vertical\"])) .line {\n min-width: 8px;\n margin: calc(var(--marker) / 2) 8px 0;\n }\n\n /* The current step takes three shares of the room, the others one, never less than their marker and line: the\n label never runs into the next step, and takes an ellipsis only when there is no room at all. */\n :host(:not([orientation=\"vertical\"])) .step:not([data-status=\"current\"]) {\n min-width: min-content;\n }\n\n :host(:not([orientation=\"vertical\"])) .step[data-status=\"current\"] {\n flex: 3 1 0;\n }\n\n :host(:not([orientation=\"vertical\"])) .step[data-status=\"current\"] .label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n :host(:not([orientation=\"vertical\"])) .step[data-status=\"current\"] .line {\n min-width: 24px;\n margin-left: 16px;\n }\n}\n";
|
|
3
3
|
export { jl_steps_default as default };
|
|
@@ -38,6 +38,8 @@ export declare class JlSteps extends JlElement {
|
|
|
38
38
|
templateCss(): string;
|
|
39
39
|
onConnect(): void;
|
|
40
40
|
private render;
|
|
41
|
+
/** A failed step's ×, a done one's check, or the step's number. */
|
|
42
|
+
private markerOf;
|
|
41
43
|
private step;
|
|
42
44
|
/** Goes back to a done step people picked, and says so. */
|
|
43
45
|
private goBackTo;
|
|
@@ -2,21 +2,28 @@ import { BASE_STYLES } from "../styles/shared.js";
|
|
|
2
2
|
import { JlElement } from "../base/jl-element.js";
|
|
3
3
|
import { clampedNumber, jsonOf, oneOf } from "../lib/attributes.js";
|
|
4
4
|
import { registerIcons } from "../lib/icons.js";
|
|
5
|
+
import { jlText } from "../lib/texts.js";
|
|
5
6
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
6
7
|
import jl_steps_default from "./jl-steps.css_raw.js";
|
|
7
8
|
import { css } from "@jadis/core";
|
|
8
|
-
import { Check } from "lucide";
|
|
9
|
+
import { Check, X } from "lucide";
|
|
9
10
|
import { jsx, jsxs } from "@jadis/core/jsx-runtime";
|
|
10
11
|
// src/molecules/jl-steps.tsx
|
|
11
|
-
registerIcons({
|
|
12
|
+
registerIcons({
|
|
13
|
+
check: Check,
|
|
14
|
+
x: X
|
|
15
|
+
});
|
|
12
16
|
var STEPS_ORIENTATIONS = ["horizontal", "vertical"];
|
|
13
17
|
var CHECK_SIZE = 14;
|
|
14
18
|
var MAX_STEPS = 100;
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
var STATUS_TEXTS = {
|
|
20
|
+
current: "stepCurrent",
|
|
21
|
+
done: "stepDone",
|
|
22
|
+
upcoming: null
|
|
23
|
+
};
|
|
24
|
+
var statusText = (status) => {
|
|
25
|
+
const key = STATUS_TEXTS[status];
|
|
26
|
+
return key === null ? "" : jlText(key);
|
|
20
27
|
};
|
|
21
28
|
var statusOf = (index, current) => {
|
|
22
29
|
if (index < current) return "done";
|
|
@@ -45,8 +52,8 @@ var JlSteps = class extends JlElement {
|
|
|
45
52
|
/** Done steps become buttons that go back to them. */
|
|
46
53
|
clickable = this.useChange(false, () => this.render(), { attribute: "clickable" });
|
|
47
54
|
/** The list's name for screen readers. */
|
|
48
|
-
label = this.useChange(
|
|
49
|
-
this._refs.list.setAttribute("aria-label", value ||
|
|
55
|
+
label = this.useChange(jlText("progress"), (value) => {
|
|
56
|
+
this._refs.list.setAttribute("aria-label", value || jlText("progress"));
|
|
50
57
|
}, { attribute: "label" });
|
|
51
58
|
_refs = this.useRefs((ref) => ({ list: ref("ol") }));
|
|
52
59
|
templateHtml() {
|
|
@@ -65,21 +72,29 @@ var JlSteps = class extends JlElement {
|
|
|
65
72
|
const current = this.current.get();
|
|
66
73
|
this._refs.list.replaceChildren(...this.items.get().map((item, index) => this.step(item, index, statusOf(index, current))));
|
|
67
74
|
}
|
|
75
|
+
/** A failed step's ×, a done one's check, or the step's number. */
|
|
76
|
+
markerOf(item, index, status) {
|
|
77
|
+
if (item.failed) return /* @__PURE__ */ jsx(JlIcon, {
|
|
78
|
+
name: "x",
|
|
79
|
+
size: CHECK_SIZE
|
|
80
|
+
});
|
|
81
|
+
return status === "done" ? /* @__PURE__ */ jsx(JlIcon, {
|
|
82
|
+
name: "check",
|
|
83
|
+
size: CHECK_SIZE
|
|
84
|
+
}) : String(index + 1);
|
|
85
|
+
}
|
|
68
86
|
step(item, index, status) {
|
|
69
87
|
const content = [/* @__PURE__ */ jsx("span", {
|
|
70
88
|
class: "marker",
|
|
71
89
|
"aria-hidden": "true",
|
|
72
|
-
children:
|
|
73
|
-
name: "check",
|
|
74
|
-
size: CHECK_SIZE
|
|
75
|
-
}) : String(index + 1)
|
|
90
|
+
children: this.markerOf(item, index, status)
|
|
76
91
|
}), /* @__PURE__ */ jsxs("span", {
|
|
77
92
|
class: "text",
|
|
78
93
|
children: [/* @__PURE__ */ jsxs("span", {
|
|
79
94
|
class: "label",
|
|
80
95
|
children: [item.label, /* @__PURE__ */ jsx("span", {
|
|
81
96
|
class: "sr-only",
|
|
82
|
-
children:
|
|
97
|
+
children: item.failed ? jlText("failedStep") : statusText(status)
|
|
83
98
|
})]
|
|
84
99
|
}), item.description === void 0 ? "" : /* @__PURE__ */ jsx("span", {
|
|
85
100
|
class: "description",
|
|
@@ -90,6 +105,7 @@ var JlSteps = class extends JlElement {
|
|
|
90
105
|
return /* @__PURE__ */ jsxs("li", {
|
|
91
106
|
class: "step",
|
|
92
107
|
"data-status": status,
|
|
108
|
+
"data-failed": item.failed ? "" : void 0,
|
|
93
109
|
"aria-current": status === "current" ? "step" : void 0,
|
|
94
110
|
children: [canGoBack ? /* @__PURE__ */ jsx("button", {
|
|
95
111
|
type: "button",
|
|
@@ -2,10 +2,11 @@ import { BASE_STYLES } from "../styles/shared.js";
|
|
|
2
2
|
import { JlElement } from "../base/jl-element.js";
|
|
3
3
|
import { oneOf } from "../lib/attributes.js";
|
|
4
4
|
import { define } from "../lib/define.js";
|
|
5
|
-
import { setOrRemove, uniqueId } from "../lib/dom.js";
|
|
6
5
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
6
|
+
import { setOrRemove, uniqueId } from "../lib/dom.js";
|
|
7
7
|
import { firstIndex, lastIndex, stepIndex } from "../lib/roving.js";
|
|
8
8
|
import { moveIndicator } from "../lib/indicator.js";
|
|
9
|
+
import { watchSizes } from "../lib/resize.js";
|
|
9
10
|
import { JlTabPanel } from "./jl-tab-panel.js";
|
|
10
11
|
import jl_tabs_default from "./jl-tabs.css_raw.js";
|
|
11
12
|
import { css } from "@jadis/core";
|
|
@@ -55,7 +56,7 @@ var JlTabs = class extends JlElement {
|
|
|
55
56
|
label = this.useChange("", (value) => setOrRemove(this._refs.list, "aria-label", value), { attribute: "label" });
|
|
56
57
|
_observers = {
|
|
57
58
|
mutations: new MutationObserver((records) => this.onMutations(records)),
|
|
58
|
-
resize:
|
|
59
|
+
resize: watchSizes(() => this.placeIndicator())
|
|
59
60
|
};
|
|
60
61
|
_refs = this.useRefs((ref) => ({
|
|
61
62
|
indicator: ref(".indicator"),
|
|
@@ -4,8 +4,9 @@ import { clampedNumber, jsonOf, oneOf } from "../lib/attributes.js";
|
|
|
4
4
|
import { followAnchor } from "../lib/floating.js";
|
|
5
5
|
import { registerIcons } from "../lib/icons.js";
|
|
6
6
|
import { CONTROL_SIZES } from "../lib/options.js";
|
|
7
|
-
import {
|
|
7
|
+
import { jlText } from "../lib/texts.js";
|
|
8
8
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
9
|
+
import { setOrRemove, uniqueId } from "../lib/dom.js";
|
|
9
10
|
import { keepInView } from "../lib/keep-in-view.js";
|
|
10
11
|
import { filterOptions, matchParts, nextEnabledIndex } from "../lib/option-filter.js";
|
|
11
12
|
import { addTags, hasTag, hasTagSeparator, splitTags } from "../lib/tags.js";
|
|
@@ -18,7 +19,6 @@ registerIcons({ x: X });
|
|
|
18
19
|
var REMOVE_ICON_SIZE = 12;
|
|
19
20
|
var NONE = -1;
|
|
20
21
|
var PLACEMENT = "bottom-start";
|
|
21
|
-
var VALUE_MISSING = "Add at least one tag.";
|
|
22
22
|
var NO_LIMIT = 0;
|
|
23
23
|
var COMMA = ",";
|
|
24
24
|
var MAX_SUGGESTIONS = 8;
|
|
@@ -413,7 +413,7 @@ var JlTagInput = class extends JlFormControl {
|
|
|
413
413
|
}
|
|
414
414
|
renderValidity() {
|
|
415
415
|
if (this.required.get() && this.value.get().length === 0) {
|
|
416
|
-
this.internals.setValidity({ valueMissing: true },
|
|
416
|
+
this.internals.setValidity({ valueMissing: true }, jlText("addTag"), this._refs.native);
|
|
417
417
|
return;
|
|
418
418
|
}
|
|
419
419
|
this.internals.setValidity({});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BASE_STYLES } from "../styles/shared.js";
|
|
2
2
|
import { JlElement } from "../base/jl-element.js";
|
|
3
3
|
import { jsonOf } from "../lib/attributes.js";
|
|
4
|
-
import { setOrRemove } from "../lib/dom.js";
|
|
5
4
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
5
|
+
import { setOrRemove } from "../lib/dom.js";
|
|
6
6
|
import jl_timeline_default from "./jl-timeline.css_raw.js";
|
|
7
7
|
import { css } from "@jadis/core";
|
|
8
8
|
import { jsx, jsxs } from "@jadis/core/jsx-runtime";
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// src/molecules/jl-toast.css?raw
|
|
2
|
-
var jl_toast_default = ":host {\n display: block;\n /* Coloured as jl-alert is, from the same tokens: a toned toast is tinted, its border and icon in its tone. */\n --fg: var(--jl-text-2);\n --bg: var(--jl-surface);\n --border: var(--jl-line);\n --bar: var(--jl-brand);\n}\n\n:host([tone=\"ok\"]),\n:host([tone=\"warn\"]),\n:host([tone=\"danger\"]),\n:host([tone=\"info\"]) {\n --border: color-mix(in srgb, var(--fg) 24%, var(--bg));\n --bar: var(--fg);\n}\n\n:host([tone=\"ok\"]) {\n --fg: var(--jl-ok);\n --bg: var(--jl-ok-soft);\n}\n\n:host([tone=\"warn\"]) {\n --fg: var(--jl-warn);\n --bg: var(--jl-warn-soft);\n}\n\n:host([tone=\"danger\"]) {\n --fg: var(--jl-danger);\n --bg: var(--jl-danger-soft);\n}\n\n:host([tone=\"info\"]) {\n --fg: var(--jl-info);\n --bg: var(--jl-info-soft);\n}\n\n.toast {\n position: relative;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px 12px 14px 16px;\n overflow: hidden;\n border: 1px solid var(--border);\n border-radius: var(--jl-radius-lg);\n background: var(--bg);\n color: var(--jl-text);\n font-size: var(--jl-font-md);\n line-height: 20px;\n box-shadow: var(--jl-shadow-lg);\n}\n\n.icon {\n margin-top: 1px;\n color: var(--fg);\n}\n\n.content {\n display: grid;\n flex: 1;\n gap: 2px;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.heading {\n font-weight: 650;\n}\n\n.text {\n color: var(--jl-muted);\n font-size: var(--jl-font-sm);\n}\n\n.heading[hidden] + .text {\n color: var(--jl-text-2);\n font-size: var(--jl-font-md);\n}\n\n.buttons {\n display: flex;\n flex: none;\n align-items: center;\n gap: 2px;\n margin: -5px -4px -5px 0;\n}\n\n.buttons:not(:has(jl-button:not([hidden]))) {\n display: none;\n}\n\n.close {\n --jl-accent: var(--fg);\n --jl-accent-soft: color-mix(in srgb, var(--fg) 12%, transparent);\n}\n\n.progress {\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 2px;\n}\n\n.bar {\n height: 100%;\n background: var(--bar);\n transform-origin: left center;\n}\n\n:host([paused]) .bar {\n opacity: 0.55;\n}\n\n/* The line still counts the time, but does not move for people who asked for less motion. */\n@media (prefers-reduced-motion: reduce) {\n .progress {\n visibility: hidden;\n }\n}\n";
|
|
2
|
+
var jl_toast_default = ":host {\n display: block;\n /* Coloured as jl-alert is, from the same tokens: a toned toast is tinted, its border and icon in its tone. */\n --fg: var(--jl-text-2);\n --bg: var(--jl-surface);\n --border: var(--jl-line);\n --bar: var(--jl-brand);\n}\n\n:host([tone=\"ok\"]),\n:host([tone=\"warn\"]),\n:host([tone=\"danger\"]),\n:host([tone=\"info\"]) {\n --border: color-mix(in srgb, var(--fg) 24%, var(--bg));\n --bar: var(--fg);\n}\n\n:host([tone=\"ok\"]) {\n --fg: var(--jl-ok);\n --bg: var(--jl-ok-soft);\n}\n\n:host([tone=\"warn\"]) {\n --fg: var(--jl-warn);\n --bg: var(--jl-warn-soft);\n}\n\n:host([tone=\"danger\"]) {\n --fg: var(--jl-danger);\n --bg: var(--jl-danger-soft);\n}\n\n:host([tone=\"info\"]) {\n --fg: var(--jl-info);\n --bg: var(--jl-info-soft);\n}\n\n.toast {\n position: relative;\n display: flex;\n align-items: flex-start;\n gap: 12px;\n padding: 14px 12px 14px 16px;\n overflow: hidden;\n border: 1px solid var(--border);\n border-radius: var(--jl-radius-lg);\n background: var(--bg);\n color: var(--jl-text);\n font-size: var(--jl-font-md);\n line-height: 20px;\n box-shadow: var(--jl-shadow-lg);\n}\n\n.icon {\n margin-top: 1px;\n color: var(--fg);\n}\n\n.content {\n display: grid;\n flex: 1;\n gap: 2px;\n min-width: 0;\n overflow-wrap: anywhere;\n}\n\n.heading {\n font-weight: 650;\n}\n\n.text {\n color: var(--jl-muted);\n font-size: var(--jl-font-sm);\n}\n\n.heading[hidden] + .text {\n color: var(--jl-text-2);\n font-size: var(--jl-font-md);\n}\n\n.buttons {\n display: flex;\n flex: none;\n align-items: center;\n gap: 2px;\n margin: -5px -4px -5px 0;\n}\n\n.buttons:not(:has(jl-button:not([hidden]))) {\n display: none;\n}\n\n.close {\n --jl-accent: var(--fg);\n --jl-accent-soft: color-mix(in srgb, var(--fg) 12%, transparent);\n}\n\n.work {\n margin-top: 8px;\n}\n\n.progress {\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 2px;\n}\n\n.bar {\n height: 100%;\n background: var(--bar);\n transform-origin: left center;\n}\n\n:host([paused]) .bar {\n opacity: 0.55;\n}\n\n/* The line still counts the time, but does not move for people who asked for less motion. */\n@media (prefers-reduced-motion: reduce) {\n .progress {\n visibility: hidden;\n }\n}\n";
|
|
3
3
|
export { jl_toast_default as default };
|
|
@@ -4,7 +4,9 @@ export declare const TOAST_TONES: readonly ToastTone[];
|
|
|
4
4
|
/**
|
|
5
5
|
* One notification: a heading, a line of text, an icon in its tone's colour, and maybe an action such as "Undo".
|
|
6
6
|
* With a `duration` it closes by itself, a thin line showing the time left; hovering or focusing it pauses the
|
|
7
|
-
* line.
|
|
7
|
+
* line. While `working`, it shows the progress of the work it tells about (a download): `progress` percent, or a
|
|
8
|
+
* bar running back and forth without it. It emits `dismiss` once it has closed. Most pages call `toast()` rather
|
|
9
|
+
* than writing it.
|
|
8
10
|
*/
|
|
9
11
|
export declare class JlToast extends JlElement {
|
|
10
12
|
static readonly selector = "jl-toast";
|
|
@@ -44,6 +46,16 @@ export declare class JlToast extends JlElement {
|
|
|
44
46
|
get(): number;
|
|
45
47
|
set(setter: number | ((prevState: number) => number)): void;
|
|
46
48
|
}>>;
|
|
49
|
+
/** Shows a progress bar under the text, while the work it tells about runs. */
|
|
50
|
+
readonly working: Readonly<Readonly<{
|
|
51
|
+
get(): boolean;
|
|
52
|
+
set(setter: boolean | ((prevState: boolean) => boolean)): void;
|
|
53
|
+
}>>;
|
|
54
|
+
/** How far the work is, in percent; `null` (no attribute) for work of unknown length. */
|
|
55
|
+
readonly progress: Readonly<Readonly<{
|
|
56
|
+
get(): number | null;
|
|
57
|
+
set(setter: number | ((prevState: number | null) => number | null) | null): void;
|
|
58
|
+
}>>;
|
|
47
59
|
private readonly _timer;
|
|
48
60
|
private readonly _hold;
|
|
49
61
|
private readonly _refs;
|
|
@@ -3,8 +3,11 @@ import { JlElement } from "../base/jl-element.js";
|
|
|
3
3
|
import { oneOf } from "../lib/attributes.js";
|
|
4
4
|
import { registerIcons } from "../lib/icons.js";
|
|
5
5
|
import { TONE_ICONS, TONE_ICON_FILLED } from "../lib/options.js";
|
|
6
|
+
import { jlText } from "../lib/texts.js";
|
|
6
7
|
import { JlIcon } from "../atoms/jl-icon.js";
|
|
7
8
|
import { JlButton } from "../atoms/jl-button.js";
|
|
9
|
+
import { optionalNumber } from "../lib/progress.js";
|
|
10
|
+
import { JlProgress } from "../atoms/jl-progress.js";
|
|
8
11
|
import jl_toast_default from "./jl-toast.css_raw.js";
|
|
9
12
|
import { css } from "@jadis/core";
|
|
10
13
|
import { CircleCheck, CircleX, Info, Sparkles, TriangleAlert, X } from "lucide";
|
|
@@ -45,7 +48,9 @@ var prefersReducedMotion = () => window.matchMedia(REDUCED_MOTION).matches;
|
|
|
45
48
|
/**
|
|
46
49
|
* One notification: a heading, a line of text, an icon in its tone's colour, and maybe an action such as "Undo".
|
|
47
50
|
* With a `duration` it closes by itself, a thin line showing the time left; hovering or focusing it pauses the
|
|
48
|
-
* line.
|
|
51
|
+
* line. While `working`, it shows the progress of the work it tells about (a download): `progress` percent, or a
|
|
52
|
+
* bar running back and forth without it. It emits `dismiss` once it has closed. Most pages call `toast()` rather
|
|
53
|
+
* than writing it.
|
|
49
54
|
*/
|
|
50
55
|
var JlToast = class extends JlElement {
|
|
51
56
|
static selector = "jl-toast";
|
|
@@ -79,6 +84,15 @@ var JlToast = class extends JlElement {
|
|
|
79
84
|
}, { attribute: "action-label" });
|
|
80
85
|
/** How long it stays, in milliseconds; 0 keeps it until it is closed. */
|
|
81
86
|
duration = this.useChange(0, () => this.startTimer(), { attribute: "duration" });
|
|
87
|
+
/** Shows a progress bar under the text, while the work it tells about runs. */
|
|
88
|
+
working = this.useChange(false, (value) => {
|
|
89
|
+
this._refs.work.hidden = !value;
|
|
90
|
+
}, { attribute: "working" });
|
|
91
|
+
/** How far the work is, in percent; `null` (no attribute) for work of unknown length. */
|
|
92
|
+
progress = this.useChange(null, (value) => this._refs.work.value.set(value), {
|
|
93
|
+
attribute: "progress",
|
|
94
|
+
parse: optionalNumber
|
|
95
|
+
});
|
|
82
96
|
_timer = {
|
|
83
97
|
animation: null,
|
|
84
98
|
entered: false
|
|
@@ -95,7 +109,8 @@ var JlToast = class extends JlElement {
|
|
|
95
109
|
icon: ref(".icon"),
|
|
96
110
|
progress: ref(".progress"),
|
|
97
111
|
text: ref(".text"),
|
|
98
|
-
toast: ref(".toast")
|
|
112
|
+
toast: ref(".toast"),
|
|
113
|
+
work: ref(JlProgress)
|
|
99
114
|
}));
|
|
100
115
|
/** Closes the toast: it leaves, hides, then emits `dismiss`. */
|
|
101
116
|
dismiss() {
|
|
@@ -146,6 +161,11 @@ var JlToast = class extends JlElement {
|
|
|
146
161
|
class: "text",
|
|
147
162
|
hidden: true
|
|
148
163
|
}),
|
|
164
|
+
/* @__PURE__ */ jsx(JlProgress, {
|
|
165
|
+
class: "work",
|
|
166
|
+
size: "sm",
|
|
167
|
+
hidden: true
|
|
168
|
+
}),
|
|
149
169
|
/* @__PURE__ */ jsx("slot", {})
|
|
150
170
|
]
|
|
151
171
|
}),
|
|
@@ -161,7 +181,7 @@ var JlToast = class extends JlElement {
|
|
|
161
181
|
variant: "ghost",
|
|
162
182
|
size: "sm",
|
|
163
183
|
icon: "x",
|
|
164
|
-
hint: "
|
|
184
|
+
hint: jlText("close"),
|
|
165
185
|
hidden: true
|
|
166
186
|
})]
|
|
167
187
|
}),
|
|
@@ -41,10 +41,13 @@ export declare class JlTooltip extends JlElement {
|
|
|
41
41
|
private isInteractive;
|
|
42
42
|
private pressStart;
|
|
43
43
|
private pressMove;
|
|
44
|
-
/** The finger lifted
|
|
44
|
+
/** The finger lifted. On a trigger that does nothing else on a tap, a tap (not a scroll) shows or hides the bubble. */
|
|
45
|
+
private pressUp;
|
|
46
|
+
/** The finger is gone: a bubble the long press showed stays a moment, then goes. */
|
|
45
47
|
private pressEnd;
|
|
46
48
|
/** The system's own long press: the bubble shows now, and the menu it would open does not, but over a link. */
|
|
47
49
|
private pressHeld;
|
|
50
|
+
/** The long press shows the bubble, and says whether there is one: without a text, the press stays a press. */
|
|
48
51
|
private openFromPress;
|
|
49
52
|
private swallowLongPress;
|
|
50
53
|
private hideBubble;
|
|
@@ -51,6 +51,7 @@ var JlTooltip = class extends JlElement {
|
|
|
51
51
|
hideTimer: 0,
|
|
52
52
|
press: {
|
|
53
53
|
down: false,
|
|
54
|
+
moved: false,
|
|
54
55
|
opened: false,
|
|
55
56
|
timer: 0,
|
|
56
57
|
x: 0,
|
|
@@ -94,7 +95,7 @@ var JlTooltip = class extends JlElement {
|
|
|
94
95
|
this.hideBubble();
|
|
95
96
|
});
|
|
96
97
|
this.on(this, "pointermove", (event) => this.pressMove(event));
|
|
97
|
-
this.on(this, "pointerup", () => this.
|
|
98
|
+
this.on(this, "pointerup", () => this.pressUp());
|
|
98
99
|
this.on(this, "pointercancel", () => this.pressEnd());
|
|
99
100
|
this.on(this, "contextmenu", (event) => this.pressHeld(event));
|
|
100
101
|
this.addEventListener("click", (event) => this.swallowLongPress(event), {
|
|
@@ -131,26 +132,34 @@ var JlTooltip = class extends JlElement {
|
|
|
131
132
|
pressStart(event) {
|
|
132
133
|
const press = this._state.press;
|
|
133
134
|
window.clearTimeout(press.timer);
|
|
134
|
-
press.opened = false;
|
|
135
|
-
if (!this.isInteractive()) {
|
|
136
|
-
if (this.isOpen()) {
|
|
137
|
-
this.close();
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
this.open();
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
135
|
press.down = true;
|
|
136
|
+
press.moved = false;
|
|
137
|
+
press.opened = false;
|
|
144
138
|
press.x = event.clientX;
|
|
145
139
|
press.y = event.clientY;
|
|
146
|
-
press.timer = window.setTimeout(() => this.openFromPress(), LONG_PRESS_MS);
|
|
140
|
+
if (this.isInteractive()) press.timer = window.setTimeout(() => this.openFromPress(), LONG_PRESS_MS);
|
|
147
141
|
}
|
|
148
142
|
pressMove(event) {
|
|
149
143
|
const press = this._state.press;
|
|
150
144
|
const moved = Math.hypot(event.clientX - press.x, event.clientY - press.y);
|
|
151
|
-
if (press.down && moved > MOVE_TOLERANCE_PX)
|
|
145
|
+
if (press.down && moved > MOVE_TOLERANCE_PX) {
|
|
146
|
+
press.moved = true;
|
|
147
|
+
window.clearTimeout(press.timer);
|
|
148
|
+
}
|
|
152
149
|
}
|
|
153
|
-
/** The finger lifted
|
|
150
|
+
/** The finger lifted. On a trigger that does nothing else on a tap, a tap (not a scroll) shows or hides the bubble. */
|
|
151
|
+
pressUp() {
|
|
152
|
+
const press = this._state.press;
|
|
153
|
+
const tapped = press.down && !press.moved;
|
|
154
|
+
this.pressEnd();
|
|
155
|
+
if (!tapped || this.isInteractive()) return;
|
|
156
|
+
if (this.isOpen()) {
|
|
157
|
+
this.close();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
this.open();
|
|
161
|
+
}
|
|
162
|
+
/** The finger is gone: a bubble the long press showed stays a moment, then goes. */
|
|
154
163
|
pressEnd() {
|
|
155
164
|
const press = this._state.press;
|
|
156
165
|
window.clearTimeout(press.timer);
|
|
@@ -162,13 +171,15 @@ var JlTooltip = class extends JlElement {
|
|
|
162
171
|
/** The system's own long press: the bubble shows now, and the menu it would open does not, but over a link. */
|
|
163
172
|
pressHeld(event) {
|
|
164
173
|
if (!this._state.press.down || !this.isInteractive()) return;
|
|
165
|
-
this.openFromPress();
|
|
166
|
-
if (!accessibleTarget(this.trigger()).matches("a[href]")) event.preventDefault();
|
|
174
|
+
if (this.openFromPress() && !accessibleTarget(this.trigger()).matches("a[href]")) event.preventDefault();
|
|
167
175
|
}
|
|
176
|
+
/** The long press shows the bubble, and says whether there is one: without a text, the press stays a press. */
|
|
168
177
|
openFromPress() {
|
|
169
178
|
window.clearTimeout(this._state.press.timer);
|
|
179
|
+
if (this.text.get() === "") return false;
|
|
170
180
|
this._state.press.opened = true;
|
|
171
181
|
this.open();
|
|
182
|
+
return true;
|
|
172
183
|
}
|
|
173
184
|
swallowLongPress(event) {
|
|
174
185
|
const press = this._state.press;
|
|
@@ -178,6 +189,7 @@ var JlTooltip = class extends JlElement {
|
|
|
178
189
|
event.stopPropagation();
|
|
179
190
|
}
|
|
180
191
|
hideBubble() {
|
|
192
|
+
window.clearTimeout(this._state.press.timer);
|
|
181
193
|
window.clearTimeout(this._state.showTimer);
|
|
182
194
|
window.clearTimeout(this._state.hideTimer);
|
|
183
195
|
this._state.following.abort();
|