@syware/jlib 0.0.0-stage → 0.1.3
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/LICENSE +21 -0
- package/README.md +133 -2
- package/dist/all.d.ts +1 -0
- package/dist/all.js +75 -0
- package/dist/atoms/jl-avatar.css_raw.js +3 -0
- package/dist/atoms/jl-avatar.d.ts +52 -0
- package/dist/atoms/jl-avatar.js +167 -0
- package/dist/atoms/jl-badge.css_raw.js +3 -0
- package/dist/atoms/jl-badge.d.ts +32 -0
- package/dist/atoms/jl-badge.js +60 -0
- package/dist/atoms/jl-button.css_raw.js +3 -0
- package/dist/atoms/jl-button.d.ts +70 -0
- package/dist/atoms/jl-button.js +146 -0
- package/dist/atoms/jl-checkbox.css_raw.js +3 -0
- package/dist/atoms/jl-checkbox.d.ts +61 -0
- package/dist/atoms/jl-checkbox.js +149 -0
- package/dist/atoms/jl-chip.css_raw.js +3 -0
- package/dist/atoms/jl-chip.d.ts +59 -0
- package/dist/atoms/jl-chip.js +164 -0
- package/dist/atoms/jl-divider.css_raw.js +3 -0
- package/dist/atoms/jl-divider.d.ts +26 -0
- package/dist/atoms/jl-divider.js +59 -0
- package/dist/atoms/jl-icon.css_raw.js +3 -0
- package/dist/atoms/jl-icon.d.ts +25 -0
- package/dist/atoms/jl-icon.js +41 -0
- package/dist/atoms/jl-input.css_raw.js +3 -0
- package/dist/atoms/jl-input.d.ts +112 -0
- package/dist/atoms/jl-input.js +202 -0
- package/dist/atoms/jl-kbd.css_raw.js +3 -0
- package/dist/atoms/jl-kbd.d.ts +17 -0
- package/dist/atoms/jl-kbd.js +62 -0
- package/dist/atoms/jl-link.css_raw.js +3 -0
- package/dist/atoms/jl-link.d.ts +37 -0
- package/dist/atoms/jl-link.js +86 -0
- package/dist/atoms/jl-progress-ring.css_raw.js +3 -0
- package/dist/atoms/jl-progress-ring.d.ts +49 -0
- package/dist/atoms/jl-progress-ring.js +132 -0
- package/dist/atoms/jl-progress.css_raw.js +3 -0
- package/dist/atoms/jl-progress.d.ts +43 -0
- package/dist/atoms/jl-progress.js +109 -0
- package/dist/atoms/jl-rating.css_raw.js +3 -0
- package/dist/atoms/jl-rating.d.ts +73 -0
- package/dist/atoms/jl-rating.js +184 -0
- package/dist/atoms/jl-select.css_raw.js +3 -0
- package/dist/atoms/jl-select.d.ts +70 -0
- package/dist/atoms/jl-select.js +146 -0
- package/dist/atoms/jl-skeleton.css_raw.js +3 -0
- package/dist/atoms/jl-skeleton.d.ts +34 -0
- package/dist/atoms/jl-skeleton.js +63 -0
- package/dist/atoms/jl-slider.css_raw.js +3 -0
- package/dist/atoms/jl-slider.d.ts +65 -0
- package/dist/atoms/jl-slider.js +143 -0
- package/dist/atoms/jl-spinner.css_raw.js +3 -0
- package/dist/atoms/jl-spinner.d.ts +16 -0
- package/dist/atoms/jl-spinner.js +26 -0
- package/dist/atoms/jl-switch.css_raw.js +3 -0
- package/dist/atoms/jl-switch.d.ts +57 -0
- package/dist/atoms/jl-switch.js +125 -0
- package/dist/atoms/jl-textarea.css_raw.js +3 -0
- package/dist/atoms/jl-textarea.d.ts +81 -0
- package/dist/atoms/jl-textarea.js +148 -0
- package/dist/base/jl-element.d.ts +16 -0
- package/dist/base/jl-element.js +35 -0
- package/dist/base/jl-form-control.d.ts +29 -0
- package/dist/base/jl-form-control.js +44 -0
- package/dist/index.d.ts +119 -0
- package/dist/index.js +72 -0
- package/dist/lib/arrow.d.ts +6 -0
- package/dist/lib/arrow.js +15 -0
- package/dist/lib/attributes.d.ts +9 -0
- package/dist/lib/attributes.js +22 -0
- package/dist/lib/avatar.d.ts +11 -0
- package/dist/lib/avatar.js +37 -0
- package/dist/lib/calendar.d.ts +48 -0
- package/dist/lib/calendar.js +166 -0
- package/dist/lib/css-length.d.ts +2 -0
- package/dist/lib/css-length.js +8 -0
- package/dist/lib/define.d.ts +9 -0
- package/dist/lib/define.js +9 -0
- package/dist/lib/dom.d.ts +4 -0
- package/dist/lib/dom.js +16 -0
- package/dist/lib/files.d.ts +18 -0
- package/dist/lib/files.js +89 -0
- package/dist/lib/floating.d.ts +13 -0
- package/dist/lib/floating.js +127 -0
- package/dist/lib/fuzzy.d.ts +26 -0
- package/dist/lib/fuzzy.js +149 -0
- package/dist/lib/highlight.d.ts +5 -0
- package/dist/lib/highlight.js +267 -0
- package/dist/lib/hotkey.d.ts +9 -0
- package/dist/lib/hotkey.js +101 -0
- package/dist/lib/icon-set.d.ts +95 -0
- package/dist/lib/icon-set.js +97 -0
- package/dist/lib/icons.d.ts +12 -0
- package/dist/lib/icons.js +39 -0
- package/dist/lib/indicator.d.ts +6 -0
- package/dist/lib/indicator.js +18 -0
- package/dist/lib/keep-in-view.d.ts +5 -0
- package/dist/lib/keep-in-view.js +15 -0
- package/dist/lib/key-shortcut.d.ts +20 -0
- package/dist/lib/key-shortcut.js +100 -0
- package/dist/lib/keycaps.d.ts +8 -0
- package/dist/lib/keycaps.js +162 -0
- package/dist/lib/locale.d.ts +4 -0
- package/dist/lib/locale.js +13 -0
- package/dist/lib/nav-tree.d.ts +9 -0
- package/dist/lib/nav-tree.js +30 -0
- package/dist/lib/numeric.d.ts +20 -0
- package/dist/lib/numeric.js +50 -0
- package/dist/lib/option-filter.d.ts +29 -0
- package/dist/lib/option-filter.js +108 -0
- package/dist/lib/option-groups.d.ts +6 -0
- package/dist/lib/option-groups.js +26 -0
- package/dist/lib/options.d.ts +5 -0
- package/dist/lib/options.js +24 -0
- package/dist/lib/pagination.d.ts +9 -0
- package/dist/lib/pagination.js +52 -0
- package/dist/lib/palette.d.ts +8 -0
- package/dist/lib/palette.js +46 -0
- package/dist/lib/progress.d.ts +20 -0
- package/dist/lib/progress.js +33 -0
- package/dist/lib/rating.d.ts +7 -0
- package/dist/lib/rating.js +26 -0
- package/dist/lib/roving-index.d.ts +10 -0
- package/dist/lib/roving-index.js +32 -0
- package/dist/lib/roving.d.ts +11 -0
- package/dist/lib/roving.js +21 -0
- package/dist/lib/slots.d.ts +2 -0
- package/dist/lib/slots.js +6 -0
- package/dist/lib/sparkline.d.ts +11 -0
- package/dist/lib/sparkline.js +42 -0
- package/dist/lib/split.d.ts +12 -0
- package/dist/lib/split.js +37 -0
- package/dist/lib/surface.d.ts +7 -0
- package/dist/lib/surface.js +28 -0
- package/dist/lib/table.d.ts +30 -0
- package/dist/lib/table.js +110 -0
- package/dist/lib/tags.d.ts +14 -0
- package/dist/lib/tags.js +29 -0
- package/dist/lib/text.d.ts +5 -0
- package/dist/lib/text.js +13 -0
- package/dist/lib/tokens.d.ts +5 -0
- package/dist/lib/tokens.js +15 -0
- package/dist/lib/tree.d.ts +16 -0
- package/dist/lib/tree.js +89 -0
- package/dist/lib/trend.d.ts +3 -0
- package/dist/lib/trend.js +15 -0
- package/dist/lib/trigger.d.ts +11 -0
- package/dist/lib/trigger.js +34 -0
- package/dist/molecules/jl-accordion-item.css_raw.js +3 -0
- package/dist/molecules/jl-accordion-item.d.ts +34 -0
- package/dist/molecules/jl-accordion-item.js +82 -0
- package/dist/molecules/jl-accordion.css_raw.js +3 -0
- package/dist/molecules/jl-accordion.d.ts +27 -0
- package/dist/molecules/jl-accordion.js +61 -0
- package/dist/molecules/jl-alert.css_raw.js +3 -0
- package/dist/molecules/jl-alert.d.ts +38 -0
- package/dist/molecules/jl-alert.js +131 -0
- package/dist/molecules/jl-avatar-group.css_raw.js +3 -0
- package/dist/molecules/jl-avatar-group.d.ts +28 -0
- package/dist/molecules/jl-avatar-group.js +69 -0
- package/dist/molecules/jl-breadcrumb.css_raw.js +3 -0
- package/dist/molecules/jl-breadcrumb.d.ts +35 -0
- package/dist/molecules/jl-breadcrumb.js +126 -0
- package/dist/molecules/jl-calendar.css_raw.js +3 -0
- package/dist/molecules/jl-calendar.d.ts +101 -0
- package/dist/molecules/jl-calendar.js +314 -0
- package/dist/molecules/jl-card.css_raw.js +3 -0
- package/dist/molecules/jl-card.d.ts +46 -0
- package/dist/molecules/jl-card.js +172 -0
- package/dist/molecules/jl-code-block.css_raw.js +3 -0
- package/dist/molecules/jl-code-block.d.ts +44 -0
- package/dist/molecules/jl-code-block.js +106 -0
- package/dist/molecules/jl-combobox.css_raw.js +3 -0
- package/dist/molecules/jl-combobox.d.ts +120 -0
- package/dist/molecules/jl-combobox.js +450 -0
- package/dist/molecules/jl-copy-button.css_raw.js +3 -0
- package/dist/molecules/jl-copy-button.d.ts +31 -0
- package/dist/molecules/jl-copy-button.js +69 -0
- package/dist/molecules/jl-date-picker.css_raw.js +3 -0
- package/dist/molecules/jl-date-picker.d.ts +109 -0
- package/dist/molecules/jl-date-picker.js +322 -0
- package/dist/molecules/jl-empty.css_raw.js +3 -0
- package/dist/molecules/jl-empty.d.ts +32 -0
- package/dist/molecules/jl-empty.js +94 -0
- package/dist/molecules/jl-field.css_raw.js +3 -0
- package/dist/molecules/jl-field.d.ts +49 -0
- package/dist/molecules/jl-field.js +147 -0
- package/dist/molecules/jl-file-drop.css_raw.js +3 -0
- package/dist/molecules/jl-file-drop.d.ts +93 -0
- package/dist/molecules/jl-file-drop.js +366 -0
- package/dist/molecules/jl-list-item.css_raw.js +3 -0
- package/dist/molecules/jl-list-item.d.ts +56 -0
- package/dist/molecules/jl-list-item.js +176 -0
- package/dist/molecules/jl-menu.css_raw.js +3 -0
- package/dist/molecules/jl-menu.d.ts +62 -0
- package/dist/molecules/jl-menu.js +288 -0
- package/dist/molecules/jl-number-input.css_raw.js +3 -0
- package/dist/molecules/jl-number-input.d.ts +81 -0
- package/dist/molecules/jl-number-input.js +220 -0
- package/dist/molecules/jl-pagination.css_raw.js +3 -0
- package/dist/molecules/jl-pagination.d.ts +59 -0
- package/dist/molecules/jl-pagination.js +172 -0
- package/dist/molecules/jl-popover.css_raw.js +3 -0
- package/dist/molecules/jl-popover.d.ts +49 -0
- package/dist/molecules/jl-popover.js +152 -0
- package/dist/molecules/jl-radio-group.css_raw.js +3 -0
- package/dist/molecules/jl-radio-group.d.ts +71 -0
- package/dist/molecules/jl-radio-group.js +202 -0
- package/dist/molecules/jl-search.css_raw.js +3 -0
- package/dist/molecules/jl-search.d.ts +71 -0
- package/dist/molecules/jl-search.js +210 -0
- package/dist/molecules/jl-segmented.css_raw.js +3 -0
- package/dist/molecules/jl-segmented.d.ts +65 -0
- package/dist/molecules/jl-segmented.js +187 -0
- package/dist/molecules/jl-stat.css_raw.js +3 -0
- package/dist/molecules/jl-stat.d.ts +55 -0
- package/dist/molecules/jl-stat.js +169 -0
- package/dist/molecules/jl-steps.css_raw.js +3 -0
- package/dist/molecules/jl-steps.d.ts +44 -0
- package/dist/molecules/jl-steps.js +118 -0
- package/dist/molecules/jl-tab-panel.css_raw.js +3 -0
- package/dist/molecules/jl-tab-panel.d.ts +35 -0
- package/dist/molecules/jl-tab-panel.js +35 -0
- package/dist/molecules/jl-tabs.css_raw.js +3 -0
- package/dist/molecules/jl-tabs.d.ts +51 -0
- package/dist/molecules/jl-tabs.js +198 -0
- package/dist/molecules/jl-tag-input.css_raw.js +3 -0
- package/dist/molecules/jl-tag-input.d.ts +103 -0
- package/dist/molecules/jl-tag-input.js +429 -0
- package/dist/molecules/jl-timeline.css_raw.js +3 -0
- package/dist/molecules/jl-timeline.d.ts +28 -0
- package/dist/molecules/jl-timeline.js +81 -0
- package/dist/molecules/jl-toast.css_raw.js +3 -0
- package/dist/molecules/jl-toast.d.ts +75 -0
- package/dist/molecules/jl-toast.js +274 -0
- package/dist/molecules/jl-tooltip.css_raw.js +3 -0
- package/dist/molecules/jl-tooltip.d.ts +44 -0
- package/dist/molecules/jl-tooltip.js +160 -0
- package/dist/organisms/jl-command-palette.css_raw.js +3 -0
- package/dist/organisms/jl-command-palette.d.ts +60 -0
- package/dist/organisms/jl-command-palette.js +285 -0
- package/dist/organisms/jl-confirm.css_raw.js +3 -0
- package/dist/organisms/jl-confirm.d.ts +56 -0
- package/dist/organisms/jl-confirm.js +132 -0
- package/dist/organisms/jl-dialog.css_raw.js +3 -0
- package/dist/organisms/jl-dialog.d.ts +43 -0
- package/dist/organisms/jl-dialog.js +120 -0
- package/dist/organisms/jl-drawer.css_raw.js +3 -0
- package/dist/organisms/jl-drawer.d.ts +50 -0
- package/dist/organisms/jl-drawer.js +141 -0
- package/dist/organisms/jl-navbar.css_raw.js +3 -0
- package/dist/organisms/jl-navbar.d.ts +32 -0
- package/dist/organisms/jl-navbar.js +121 -0
- package/dist/organisms/jl-page-header.css_raw.js +3 -0
- package/dist/organisms/jl-page-header.d.ts +26 -0
- package/dist/organisms/jl-page-header.js +85 -0
- package/dist/organisms/jl-side-nav.css_raw.js +3 -0
- package/dist/organisms/jl-side-nav.d.ts +60 -0
- package/dist/organisms/jl-side-nav.js +269 -0
- package/dist/organisms/jl-table.css_raw.js +3 -0
- package/dist/organisms/jl-table.d.ts +109 -0
- package/dist/organisms/jl-table.js +318 -0
- package/dist/organisms/jl-toaster.css_raw.js +3 -0
- package/dist/organisms/jl-toaster.d.ts +48 -0
- package/dist/organisms/jl-toaster.js +142 -0
- package/dist/organisms/jl-tree.css_raw.js +3 -0
- package/dist/organisms/jl-tree.d.ts +59 -0
- package/dist/organisms/jl-tree.js +198 -0
- package/dist/styles/base.css_raw.js +3 -0
- package/dist/styles/control.css_raw.js +3 -0
- package/dist/styles/floating.css_raw.js +3 -0
- package/dist/styles/shared.d.ts +8 -0
- package/dist/styles/shared.js +14 -0
- package/dist/styles/tokens.css_raw.js +3 -0
- package/dist/templates/jl-app-shell.css_raw.js +3 -0
- package/dist/templates/jl-app-shell.d.ts +37 -0
- package/dist/templates/jl-app-shell.js +150 -0
- package/dist/templates/jl-split-view.css_raw.js +3 -0
- package/dist/templates/jl-split-view.d.ts +49 -0
- package/dist/templates/jl-split-view.js +149 -0
- package/dist/tokens.css +188 -0
- package/dist/types/calendar.types.d.ts +11 -0
- package/dist/types/files.types.d.ts +23 -0
- package/dist/types/floating.types.d.ts +13 -0
- package/dist/types/fuzzy.types.d.ts +10 -0
- package/dist/types/highlight.types.d.ts +6 -0
- package/dist/types/hotkey.types.d.ts +19 -0
- package/dist/types/jl-accordion.types.d.ts +2 -0
- package/dist/types/jl-avatar.types.d.ts +10 -0
- package/dist/types/jl-breadcrumb.types.d.ts +6 -0
- package/dist/types/jl-button.types.d.ts +3 -0
- package/dist/types/jl-card.types.d.ts +2 -0
- package/dist/types/jl-chip.types.d.ts +1 -0
- package/dist/types/jl-combobox.types.d.ts +8 -0
- package/dist/types/jl-command-palette.types.d.ts +22 -0
- package/dist/types/jl-confirm.types.d.ts +10 -0
- package/dist/types/jl-dialog.types.d.ts +1 -0
- package/dist/types/jl-divider.types.d.ts +2 -0
- package/dist/types/jl-drawer.types.d.ts +4 -0
- package/dist/types/jl-empty.types.d.ts +2 -0
- package/dist/types/jl-field.types.d.ts +2 -0
- package/dist/types/jl-input.types.d.ts +1 -0
- package/dist/types/jl-link.types.d.ts +2 -0
- package/dist/types/jl-menu.types.d.ts +22 -0
- package/dist/types/jl-navbar.types.d.ts +6 -0
- package/dist/types/jl-progress.types.d.ts +3 -0
- package/dist/types/jl-radio-group.types.d.ts +10 -0
- package/dist/types/jl-segmented.types.d.ts +7 -0
- package/dist/types/jl-select.types.d.ts +12 -0
- package/dist/types/jl-side-nav.types.d.ts +17 -0
- package/dist/types/jl-skeleton.types.d.ts +2 -0
- package/dist/types/jl-slider.types.d.ts +5 -0
- package/dist/types/jl-split-view.types.d.ts +2 -0
- package/dist/types/jl-stat.types.d.ts +2 -0
- package/dist/types/jl-steps.types.d.ts +8 -0
- package/dist/types/jl-switch.types.d.ts +1 -0
- package/dist/types/jl-table.types.d.ts +30 -0
- package/dist/types/jl-tabs.types.d.ts +2 -0
- package/dist/types/jl-timeline.types.d.ts +10 -0
- package/dist/types/jl-toast.types.d.ts +2 -0
- package/dist/types/jl-toaster.types.d.ts +23 -0
- package/dist/types/jl-tree.types.d.ts +26 -0
- package/dist/types/key-shortcut.types.d.ts +9 -0
- package/dist/types/keycaps.types.d.ts +7 -0
- package/dist/types/option-filter.types.d.ts +10 -0
- package/dist/types/options.types.d.ts +4 -0
- package/dist/types/pagination.types.d.ts +8 -0
- package/dist/types/roving-index.types.d.ts +2 -0
- package/dist/types/sparkline.types.d.ts +11 -0
- package/package.json +102 -4
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { JlFormControl } from '../base/jl-form-control';
|
|
2
|
+
import type { SelectOption } from '../types/jl-select.types';
|
|
3
|
+
import type { ControlSize } from '../types/options.types';
|
|
4
|
+
/**
|
|
5
|
+
* A choice among a list, on the browser's own `<select>`: its list opens the way the platform does it. The choices
|
|
6
|
+
* come from `options` (JSON) or from `<option>` and `<optgroup>` elements written inside it.
|
|
7
|
+
*/
|
|
8
|
+
export declare class JlSelect extends JlFormControl {
|
|
9
|
+
static readonly selector = "jl-select";
|
|
10
|
+
readonly events: Readonly<import("@jadis/core").UseEventsHandler<{
|
|
11
|
+
change: string;
|
|
12
|
+
}>>;
|
|
13
|
+
/** The choices; an option with a `group` goes under that heading. Empty: the `<option>` children are used. */
|
|
14
|
+
readonly options: Readonly<Readonly<{
|
|
15
|
+
get(): SelectOption[];
|
|
16
|
+
set(setter: SelectOption[] | ((prevState: SelectOption[]) => SelectOption[])): void;
|
|
17
|
+
}>>;
|
|
18
|
+
readonly value: Readonly<Readonly<{
|
|
19
|
+
get(): string;
|
|
20
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
21
|
+
}>>;
|
|
22
|
+
/** Shown while nothing is chosen; it cannot be picked back from the list. */
|
|
23
|
+
readonly placeholder: Readonly<Readonly<{
|
|
24
|
+
get(): string;
|
|
25
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
26
|
+
}>>;
|
|
27
|
+
readonly size: Readonly<Readonly<{
|
|
28
|
+
get(): ControlSize;
|
|
29
|
+
set(setter: ((prevState: ControlSize) => ControlSize) | ControlSize): void;
|
|
30
|
+
}>>;
|
|
31
|
+
/** The field's name for screen readers, when no visible label names it. */
|
|
32
|
+
readonly label: Readonly<Readonly<{
|
|
33
|
+
get(): string;
|
|
34
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
35
|
+
}>>;
|
|
36
|
+
readonly required: Readonly<Readonly<{
|
|
37
|
+
get(): boolean;
|
|
38
|
+
set(setter: boolean | ((prevState: boolean) => boolean)): void;
|
|
39
|
+
}>>;
|
|
40
|
+
readonly disabled: Readonly<Readonly<{
|
|
41
|
+
get(): boolean;
|
|
42
|
+
set(setter: boolean | ((prevState: boolean) => boolean)): void;
|
|
43
|
+
}>>;
|
|
44
|
+
/** Draws the field in the danger colour, for an error the page found itself. */
|
|
45
|
+
readonly invalid: Readonly<Readonly<{
|
|
46
|
+
get(): boolean;
|
|
47
|
+
set(setter: boolean | ((prevState: boolean) => boolean)): void;
|
|
48
|
+
}>>;
|
|
49
|
+
private readonly _form;
|
|
50
|
+
private readonly _refs;
|
|
51
|
+
focus(options?: FocusOptions): void;
|
|
52
|
+
templateHtml(): Node;
|
|
53
|
+
templateCss(): string;
|
|
54
|
+
onConnect(): void;
|
|
55
|
+
protected resetValue(): void;
|
|
56
|
+
/** The browser calls it for a disabled fieldset and for the element's own disabled attribute, even before render. */
|
|
57
|
+
protected setDisabledByForm(disabled: boolean): void;
|
|
58
|
+
private renderDisabled;
|
|
59
|
+
/** The options from `options`, or else copies of the `<option>` and `<optgroup>` the page wrote inside. */
|
|
60
|
+
private optionNodes;
|
|
61
|
+
private placeholderNodes;
|
|
62
|
+
private renderOptions;
|
|
63
|
+
/** Shows the chosen option; the form gets what is shown. */
|
|
64
|
+
private renderValue;
|
|
65
|
+
/**
|
|
66
|
+
* The option to show: the one with the value, or else what a native select shows, the placeholder or the first
|
|
67
|
+
* option that can be chosen.
|
|
68
|
+
*/
|
|
69
|
+
private shownIndex;
|
|
70
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { BASE_STYLES, CONTROL_STYLES } from "../styles/shared.js";
|
|
2
|
+
import { JlFormControl } from "../base/jl-form-control.js";
|
|
3
|
+
import { jsonOf, oneOf } from "../lib/attributes.js";
|
|
4
|
+
import { registerIcons } from "../lib/icons.js";
|
|
5
|
+
import { CONTROL_SIZES } from "../lib/options.js";
|
|
6
|
+
import { setOrRemove } from "../lib/dom.js";
|
|
7
|
+
import { JlIcon } from "./jl-icon.js";
|
|
8
|
+
import { groupOptions } from "../lib/option-groups.js";
|
|
9
|
+
import jl_select_default from "./jl-select.css_raw.js";
|
|
10
|
+
import { css } from "@jadis/core";
|
|
11
|
+
import { ChevronDown } from "lucide";
|
|
12
|
+
import { jsx, jsxs } from "@jadis/core/jsx-runtime";
|
|
13
|
+
// src/atoms/jl-select.tsx
|
|
14
|
+
registerIcons({ "chevron-down": ChevronDown });
|
|
15
|
+
var CHEVRON_SIZE = 16;
|
|
16
|
+
var LIGHT_OPTIONS = ":scope > option, :scope > optgroup";
|
|
17
|
+
var NO_VALUE = "";
|
|
18
|
+
var PLACEHOLDER_CLASS = "placeholder";
|
|
19
|
+
var optionElement = (option) => /* @__PURE__ */ jsx("option", {
|
|
20
|
+
value: option.value,
|
|
21
|
+
disabled: option.disabled === true,
|
|
22
|
+
children: option.label
|
|
23
|
+
});
|
|
24
|
+
var groupNodes = (group) => {
|
|
25
|
+
const options = group.options.map(optionElement);
|
|
26
|
+
return group.label === null ? options : [/* @__PURE__ */ jsx("optgroup", {
|
|
27
|
+
label: group.label,
|
|
28
|
+
children: options
|
|
29
|
+
})];
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* A choice among a list, on the browser's own `<select>`: its list opens the way the platform does it. The choices
|
|
33
|
+
* come from `options` (JSON) or from `<option>` and `<optgroup>` elements written inside it.
|
|
34
|
+
*/
|
|
35
|
+
var JlSelect = class extends JlFormControl {
|
|
36
|
+
static selector = "jl-select";
|
|
37
|
+
events = this.useEvents();
|
|
38
|
+
/** The choices; an option with a `group` goes under that heading. Empty: the `<option>` children are used. */
|
|
39
|
+
options = this.useChange([], () => this.renderOptions(), {
|
|
40
|
+
attribute: "options",
|
|
41
|
+
parse: jsonOf([])
|
|
42
|
+
});
|
|
43
|
+
value = this.useChange(NO_VALUE, () => this.renderValue(), { attribute: "value" });
|
|
44
|
+
/** Shown while nothing is chosen; it cannot be picked back from the list. */
|
|
45
|
+
placeholder = this.useChange("", () => this.renderOptions(), { attribute: "placeholder" });
|
|
46
|
+
size = this.useChange("md", (value) => this.reflect("size", value), {
|
|
47
|
+
attribute: "size",
|
|
48
|
+
parse: oneOf(CONTROL_SIZES, "md")
|
|
49
|
+
});
|
|
50
|
+
/** The field's name for screen readers, when no visible label names it. */
|
|
51
|
+
label = this.useChange("", (value) => setOrRemove(this._refs.native, "aria-label", value), { attribute: "label" });
|
|
52
|
+
required = this.useChange(false, (value) => {
|
|
53
|
+
this._refs.native.required = value;
|
|
54
|
+
this.reflect("required", value);
|
|
55
|
+
this.renderValue();
|
|
56
|
+
}, { attribute: "required" });
|
|
57
|
+
disabled = this.useChange(false, (value) => {
|
|
58
|
+
this.reflect("disabled", value);
|
|
59
|
+
this.renderDisabled();
|
|
60
|
+
}, { attribute: "disabled" });
|
|
61
|
+
/** Draws the field in the danger colour, for an error the page found itself. */
|
|
62
|
+
invalid = this.useChange(false, (value) => {
|
|
63
|
+
this.reflect("invalid", value);
|
|
64
|
+
this._refs.native.toggleAttribute("aria-invalid", value);
|
|
65
|
+
}, { attribute: "invalid" });
|
|
66
|
+
_form = { disabled: false };
|
|
67
|
+
_refs = this.useRefs((ref) => ({ native: ref("select") }));
|
|
68
|
+
focus(options) {
|
|
69
|
+
this._refs.native.focus(options);
|
|
70
|
+
}
|
|
71
|
+
templateHtml() {
|
|
72
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
73
|
+
class: "control",
|
|
74
|
+
attrs: { part: "base" },
|
|
75
|
+
children: [/* @__PURE__ */ jsx("select", { class: "native" }), /* @__PURE__ */ jsx(JlIcon, {
|
|
76
|
+
class: "chevron",
|
|
77
|
+
name: "chevron-down",
|
|
78
|
+
size: CHEVRON_SIZE
|
|
79
|
+
})]
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
templateCss() {
|
|
83
|
+
return css`${BASE_STYLES}${CONTROL_STYLES}${jl_select_default}`;
|
|
84
|
+
}
|
|
85
|
+
onConnect() {
|
|
86
|
+
const native = this._refs.native;
|
|
87
|
+
this.on(native, "change", () => {
|
|
88
|
+
this.value.set(native.value);
|
|
89
|
+
this.events.emit("change", native.value);
|
|
90
|
+
});
|
|
91
|
+
this.renderOptions();
|
|
92
|
+
}
|
|
93
|
+
resetValue() {
|
|
94
|
+
this.value.set(this.getAttribute("value") ?? NO_VALUE);
|
|
95
|
+
}
|
|
96
|
+
/** The browser calls it for a disabled fieldset and for the element's own disabled attribute, even before render. */
|
|
97
|
+
setDisabledByForm(disabled) {
|
|
98
|
+
this._form.disabled = disabled;
|
|
99
|
+
this.whenRendered(() => this.renderDisabled());
|
|
100
|
+
}
|
|
101
|
+
renderDisabled() {
|
|
102
|
+
this._refs.native.disabled = this.disabled.get() || this._form.disabled;
|
|
103
|
+
}
|
|
104
|
+
/** The options from `options`, or else copies of the `<option>` and `<optgroup>` the page wrote inside. */
|
|
105
|
+
optionNodes() {
|
|
106
|
+
const options = this.options.get();
|
|
107
|
+
if (options.length > 0) return groupOptions(options).flatMap(groupNodes);
|
|
108
|
+
return [...this.querySelectorAll(LIGHT_OPTIONS)].map((node) => node.cloneNode(true));
|
|
109
|
+
}
|
|
110
|
+
placeholderNodes() {
|
|
111
|
+
const placeholder = this.placeholder.get();
|
|
112
|
+
if (placeholder === "") return [];
|
|
113
|
+
return [/* @__PURE__ */ jsx("option", {
|
|
114
|
+
class: PLACEHOLDER_CLASS,
|
|
115
|
+
value: NO_VALUE,
|
|
116
|
+
disabled: true,
|
|
117
|
+
hidden: true,
|
|
118
|
+
children: placeholder
|
|
119
|
+
})];
|
|
120
|
+
}
|
|
121
|
+
renderOptions() {
|
|
122
|
+
this._refs.native.replaceChildren(...this.placeholderNodes(), ...this.optionNodes());
|
|
123
|
+
this.renderValue();
|
|
124
|
+
}
|
|
125
|
+
/** Shows the chosen option; the form gets what is shown. */
|
|
126
|
+
renderValue() {
|
|
127
|
+
const native = this._refs.native;
|
|
128
|
+
native.selectedIndex = this.shownIndex();
|
|
129
|
+
this.reflect("placeholder-shown", native.selectedOptions[0]?.classList.contains(PLACEHOLDER_CLASS) === true);
|
|
130
|
+
this.internals.setFormValue(native.value);
|
|
131
|
+
this.mirrorValidity(native);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* The option to show: the one with the value, or else what a native select shows, the placeholder or the first
|
|
135
|
+
* option that can be chosen.
|
|
136
|
+
*/
|
|
137
|
+
shownIndex() {
|
|
138
|
+
const options = [...this._refs.native.options];
|
|
139
|
+
const value = this.value.get();
|
|
140
|
+
const chosen = options.findIndex((option) => option.value === value);
|
|
141
|
+
if (chosen !== -1) return chosen;
|
|
142
|
+
return options.findIndex((option) => option.classList.contains(PLACEHOLDER_CLASS) || !option.disabled);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
JlSelect.register();
|
|
146
|
+
export { JlSelect };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// src/atoms/jl-skeleton.css?raw
|
|
2
|
+
var jl_skeleton_default = ":host {\n display: block;\n --base: var(--jl-surface-3);\n --shine: var(--jl-surface-2);\n}\n\n:host([shape=\"circle\"]) {\n display: inline-block;\n vertical-align: middle;\n}\n\n.bones {\n display: grid;\n gap: 0.55em;\n width: var(--width, 100%);\n}\n\n.bone {\n display: block;\n height: var(--height, 0.8em);\n border-radius: var(--jl-radius-xs);\n background: linear-gradient(90deg, var(--base) 30%, var(--shine) 50%, var(--base) 70%) 0 0 / 300% 100%;\n animation: shimmer 1.8s ease-in-out infinite;\n}\n\n.bone:last-child:not(:first-child) {\n width: 60%;\n}\n\n:host([shape=\"rect\"]) .bone {\n height: var(--height, 96px);\n border-radius: var(--jl-radius);\n}\n\n:host([shape=\"circle\"]) .bones {\n width: var(--width, 40px);\n}\n\n:host([shape=\"circle\"]) .bone {\n width: 100%;\n height: var(--height, auto);\n aspect-ratio: 1;\n border-radius: 50%;\n}\n\n@keyframes shimmer {\n from {\n background-position: 100% 0;\n }\n\n to {\n background-position: 0 0;\n }\n}\n\n/* A shortened endless animation would flicker: without motion, the placeholder stays still. */\n@media (prefers-reduced-motion: reduce) {\n .bone {\n animation: none;\n }\n}\n";
|
|
3
|
+
export { jl_skeleton_default as default };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { JlElement } from '../base/jl-element';
|
|
2
|
+
import type { SkeletonShape } from '../types/jl-skeleton.types';
|
|
3
|
+
export declare const SKELETON_SHAPES: readonly SkeletonShape[];
|
|
4
|
+
/**
|
|
5
|
+
* A placeholder that shimmers where content is loading: lines of `text`, a `rect` for an image or a card, a
|
|
6
|
+
* `circle` for an avatar. Screen readers skip it; mark the region it fills with `aria-busy="true"`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class JlSkeleton extends JlElement {
|
|
9
|
+
static readonly selector = "jl-skeleton";
|
|
10
|
+
readonly shape: Readonly<Readonly<{
|
|
11
|
+
get(): SkeletonShape;
|
|
12
|
+
set(setter: ((prevState: SkeletonShape) => SkeletonShape) | SkeletonShape): void;
|
|
13
|
+
}>>;
|
|
14
|
+
/** A CSS length; a plain number is in pixels. Text and blocks take the whole width by default. */
|
|
15
|
+
readonly width: Readonly<Readonly<{
|
|
16
|
+
get(): string;
|
|
17
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
18
|
+
}>>;
|
|
19
|
+
/** A CSS length; a plain number is in pixels. A circle takes its width when it has no height. */
|
|
20
|
+
readonly height: Readonly<Readonly<{
|
|
21
|
+
get(): string;
|
|
22
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
23
|
+
}>>;
|
|
24
|
+
/** For text: how many lines; the last of several is shorter, as a paragraph's is. */
|
|
25
|
+
readonly lines: Readonly<Readonly<{
|
|
26
|
+
get(): number;
|
|
27
|
+
set(setter: number | ((prevState: number) => number)): void;
|
|
28
|
+
}>>;
|
|
29
|
+
private readonly _refs;
|
|
30
|
+
templateHtml(): Node;
|
|
31
|
+
templateCss(): string;
|
|
32
|
+
private renderBones;
|
|
33
|
+
private setLength;
|
|
34
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { BASE_STYLES } from "../styles/shared.js";
|
|
2
|
+
import { JlElement } from "../base/jl-element.js";
|
|
3
|
+
import { clampedNumber, oneOf } from "../lib/attributes.js";
|
|
4
|
+
import { cssLength } from "../lib/css-length.js";
|
|
5
|
+
import jl_skeleton_default from "./jl-skeleton.css_raw.js";
|
|
6
|
+
import { css } from "@jadis/core";
|
|
7
|
+
import { jsx } from "@jadis/core/jsx-runtime";
|
|
8
|
+
// src/atoms/jl-skeleton.tsx
|
|
9
|
+
var SKELETON_SHAPES = [
|
|
10
|
+
"text",
|
|
11
|
+
"rect",
|
|
12
|
+
"circle"
|
|
13
|
+
];
|
|
14
|
+
var MIN_LINES = 1;
|
|
15
|
+
var MAX_LINES = 20;
|
|
16
|
+
/**
|
|
17
|
+
* A placeholder that shimmers where content is loading: lines of `text`, a `rect` for an image or a card, a
|
|
18
|
+
* `circle` for an avatar. Screen readers skip it; mark the region it fills with `aria-busy="true"`.
|
|
19
|
+
*/
|
|
20
|
+
var JlSkeleton = class extends JlElement {
|
|
21
|
+
static selector = "jl-skeleton";
|
|
22
|
+
shape = this.useChange("text", (value) => {
|
|
23
|
+
this.reflect("shape", value);
|
|
24
|
+
this.renderBones();
|
|
25
|
+
}, {
|
|
26
|
+
attribute: "shape",
|
|
27
|
+
parse: oneOf(SKELETON_SHAPES, "text")
|
|
28
|
+
});
|
|
29
|
+
/** A CSS length; a plain number is in pixels. Text and blocks take the whole width by default. */
|
|
30
|
+
width = this.useChange("", (value) => this.setLength("--width", value), { attribute: "width" });
|
|
31
|
+
/** A CSS length; a plain number is in pixels. A circle takes its width when it has no height. */
|
|
32
|
+
height = this.useChange("", (value) => this.setLength("--height", value), { attribute: "height" });
|
|
33
|
+
/** For text: how many lines; the last of several is shorter, as a paragraph's is. */
|
|
34
|
+
lines = this.useChange(MIN_LINES, () => this.renderBones(), {
|
|
35
|
+
attribute: "lines",
|
|
36
|
+
parse: clampedNumber(MIN_LINES, MIN_LINES, MAX_LINES)
|
|
37
|
+
});
|
|
38
|
+
_refs = this.useRefs((ref) => ({ bones: ref(".bones") }));
|
|
39
|
+
templateHtml() {
|
|
40
|
+
return /* @__PURE__ */ jsx("span", {
|
|
41
|
+
class: "bones",
|
|
42
|
+
"aria-hidden": "true",
|
|
43
|
+
attrs: { part: "base" }
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
templateCss() {
|
|
47
|
+
return css`${BASE_STYLES}${jl_skeleton_default}`;
|
|
48
|
+
}
|
|
49
|
+
renderBones() {
|
|
50
|
+
const count = this.shape.get() === "text" ? Math.round(this.lines.get()) : 1;
|
|
51
|
+
this._refs.bones.replaceChildren(...Array.from({ length: count }, () => /* @__PURE__ */ jsx("span", { class: "bone" })));
|
|
52
|
+
}
|
|
53
|
+
setLength(property, value) {
|
|
54
|
+
const length = cssLength(value);
|
|
55
|
+
if (length === "") {
|
|
56
|
+
this.style.removeProperty(property);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.style.setProperty(property, length);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
JlSkeleton.register();
|
|
63
|
+
export { JlSkeleton, SKELETON_SHAPES };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// src/atoms/jl-slider.css?raw
|
|
2
|
+
var jl_slider_default = ":host {\n display: block;\n --thumb: 16px;\n --track: 4px;\n --fill: var(--jl-accent);\n --rest: var(--jl-line-strong);\n}\n\n.slider {\n display: flex;\n align-items: flex-start;\n gap: 12px;\n}\n\n.track-area {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n\n/* The track fills up to the thumb's centre, which travels the width minus the thumb itself. */\n.native {\n --stop: calc(var(--thumb) / 2 + (100% - var(--thumb)) * var(--fraction, 0));\n display: block;\n width: 100%;\n height: 20px;\n margin: 0;\n background: transparent;\n cursor: pointer;\n appearance: none;\n}\n\n.native:focus-visible {\n box-shadow: none;\n}\n\n.native::-webkit-slider-runnable-track {\n height: var(--track);\n border-radius: var(--jl-radius-pill);\n background: linear-gradient(to right, var(--fill) var(--stop), var(--rest) var(--stop));\n}\n\n.native::-moz-range-track {\n height: var(--track);\n border-radius: var(--jl-radius-pill);\n background: linear-gradient(to right, var(--fill) var(--stop), var(--rest) var(--stop));\n}\n\n.native::-webkit-slider-thumb {\n width: var(--thumb);\n height: var(--thumb);\n margin-top: calc((var(--track) - var(--thumb)) / 2);\n border: 2px solid var(--fill);\n border-radius: 50%;\n background: var(--jl-surface);\n appearance: none;\n transition:\n box-shadow var(--jl-fast) var(--jl-ease),\n transform var(--jl-fast) var(--jl-ease);\n}\n\n.native::-moz-range-thumb {\n box-sizing: border-box;\n width: var(--thumb);\n height: var(--thumb);\n border: 2px solid var(--fill);\n border-radius: 50%;\n background: var(--jl-surface);\n}\n\n.native:hover::-webkit-slider-thumb {\n transform: scale(1.1);\n}\n\n.native:focus-visible::-webkit-slider-thumb {\n box-shadow: var(--jl-focus-ring);\n}\n\n.native:focus-visible::-moz-range-thumb {\n box-shadow: var(--jl-focus-ring);\n}\n\n:host([disabled]),\n:host(:disabled) {\n --fill: var(--jl-faint);\n}\n\n:host([disabled]) .native,\n:host(:disabled) .native {\n cursor: not-allowed;\n opacity: 0.6;\n}\n\n:host([disabled]) .native:hover::-webkit-slider-thumb,\n:host(:disabled) .native:hover::-webkit-slider-thumb {\n transform: none;\n}\n\n.output {\n min-width: 3ch;\n color: var(--jl-text);\n font-family: var(--jl-font-mono);\n font-size: var(--jl-font-sm);\n font-variant-numeric: tabular-nums;\n line-height: 20px;\n text-align: right;\n}\n\n.marks {\n position: relative;\n height: 8px;\n margin-top: 2px;\n}\n\n:host([has-labels]) .marks {\n height: 26px;\n}\n\n.mark {\n position: absolute;\n top: 0;\n left: calc(var(--thumb) / 2 + (100% - var(--thumb)) * var(--at));\n display: grid;\n justify-items: center;\n gap: 2px;\n transform: translateX(-50%);\n}\n\n.tick {\n width: 1px;\n height: 6px;\n background: var(--jl-line-strong);\n}\n\n.mark-label {\n color: var(--jl-muted);\n font-size: var(--jl-font-xs);\n line-height: 16px;\n white-space: nowrap;\n}\n\n.mark[data-edge=\"start\"] .mark-label {\n transform: translateX(calc(50% - var(--thumb) / 2));\n}\n\n.mark[data-edge=\"end\"] .mark-label {\n transform: translateX(calc(var(--thumb) / 2 - 50%));\n}\n";
|
|
3
|
+
export { jl_slider_default as default };
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { JlFormControl } from '../base/jl-form-control';
|
|
2
|
+
import type { SliderMark } from '../types/jl-slider.types';
|
|
3
|
+
/**
|
|
4
|
+
* A number picked by dragging along a track, on the browser's own range input: the arrow keys, Page Up/Down,
|
|
5
|
+
* Home and End move it. The track fills in the accent colour up to the thumb.
|
|
6
|
+
*/
|
|
7
|
+
export declare class JlSlider extends JlFormControl {
|
|
8
|
+
static readonly selector = "jl-slider";
|
|
9
|
+
readonly events: Readonly<import("@jadis/core").UseEventsHandler<{
|
|
10
|
+
input: number;
|
|
11
|
+
change: number;
|
|
12
|
+
}>>;
|
|
13
|
+
readonly min: Readonly<Readonly<{
|
|
14
|
+
get(): number;
|
|
15
|
+
set(setter: number | ((prevState: number) => number)): void;
|
|
16
|
+
}>>;
|
|
17
|
+
readonly max: Readonly<Readonly<{
|
|
18
|
+
get(): number;
|
|
19
|
+
set(setter: number | ((prevState: number) => number)): void;
|
|
20
|
+
}>>;
|
|
21
|
+
readonly step: Readonly<Readonly<{
|
|
22
|
+
get(): number;
|
|
23
|
+
set(setter: number | ((prevState: number) => number)): void;
|
|
24
|
+
}>>;
|
|
25
|
+
/** The number; it is brought between `min` and `max`, on a `step`, as the native input does. */
|
|
26
|
+
readonly value: Readonly<Readonly<{
|
|
27
|
+
get(): number;
|
|
28
|
+
set(setter: number | ((prevState: number) => number)): void;
|
|
29
|
+
}>>;
|
|
30
|
+
/** Shows the number at the end of the track. */
|
|
31
|
+
readonly showValue: Readonly<Readonly<{
|
|
32
|
+
get(): boolean;
|
|
33
|
+
set(setter: boolean | ((prevState: boolean) => boolean)): void;
|
|
34
|
+
}>>;
|
|
35
|
+
/** Ticks under the track: numbers, or `{ value, label }` for a tick with a label. */
|
|
36
|
+
readonly marks: Readonly<Readonly<{
|
|
37
|
+
get(): (number | SliderMark)[];
|
|
38
|
+
set(setter: (number | SliderMark)[] | ((prevState: (number | SliderMark)[]) => (number | SliderMark)[])): void;
|
|
39
|
+
}>>;
|
|
40
|
+
/** The slider's name for screen readers, when no visible label names it. */
|
|
41
|
+
readonly label: Readonly<Readonly<{
|
|
42
|
+
get(): string;
|
|
43
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
44
|
+
}>>;
|
|
45
|
+
readonly disabled: Readonly<Readonly<{
|
|
46
|
+
get(): boolean;
|
|
47
|
+
set(setter: boolean | ((prevState: boolean) => boolean)): void;
|
|
48
|
+
}>>;
|
|
49
|
+
private readonly _form;
|
|
50
|
+
private readonly _refs;
|
|
51
|
+
focus(options?: FocusOptions): void;
|
|
52
|
+
templateHtml(): Node;
|
|
53
|
+
templateCss(): string;
|
|
54
|
+
onConnect(): void;
|
|
55
|
+
protected resetValue(): void;
|
|
56
|
+
/** The browser calls it for a disabled fieldset and for the element's own disabled attribute, even before render. */
|
|
57
|
+
protected setDisabledByForm(disabled: boolean): void;
|
|
58
|
+
private renderDisabled;
|
|
59
|
+
private render;
|
|
60
|
+
/** New bounds move the thumb and the marks. */
|
|
61
|
+
private renderRange;
|
|
62
|
+
/** The fill, the shown number and the form's value, from the value the native input kept. */
|
|
63
|
+
private renderPosition;
|
|
64
|
+
private renderMarks;
|
|
65
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { BASE_STYLES } from "../styles/shared.js";
|
|
2
|
+
import { JlFormControl } from "../base/jl-form-control.js";
|
|
3
|
+
import { jsonOf } from "../lib/attributes.js";
|
|
4
|
+
import { setOrRemove } from "../lib/dom.js";
|
|
5
|
+
import { fractionOf, marksOf, parseNumber } from "../lib/numeric.js";
|
|
6
|
+
import jl_slider_default from "./jl-slider.css_raw.js";
|
|
7
|
+
import { css } from "@jadis/core";
|
|
8
|
+
import { jsx, jsxs } from "@jadis/core/jsx-runtime";
|
|
9
|
+
// src/atoms/jl-slider.tsx
|
|
10
|
+
var DEFAULT_MIN = 0;
|
|
11
|
+
var DEFAULT_MAX = 100;
|
|
12
|
+
var DEFAULT_STEP = 1;
|
|
13
|
+
var DEFAULT_VALUE = 0;
|
|
14
|
+
var EDGES = /* @__PURE__ */ new Map([[0, "start"], [1, "end"]]);
|
|
15
|
+
/**
|
|
16
|
+
* A number picked by dragging along a track, on the browser's own range input: the arrow keys, Page Up/Down,
|
|
17
|
+
* Home and End move it. The track fills in the accent colour up to the thumb.
|
|
18
|
+
*/
|
|
19
|
+
var JlSlider = class extends JlFormControl {
|
|
20
|
+
static selector = "jl-slider";
|
|
21
|
+
events = this.useEvents();
|
|
22
|
+
min = this.useChange(DEFAULT_MIN, () => this.renderRange(), { attribute: "min" });
|
|
23
|
+
max = this.useChange(DEFAULT_MAX, () => this.renderRange(), { attribute: "max" });
|
|
24
|
+
step = this.useChange(DEFAULT_STEP, () => this.render(), { attribute: "step" });
|
|
25
|
+
/** The number; it is brought between `min` and `max`, on a `step`, as the native input does. */
|
|
26
|
+
value = this.useChange(DEFAULT_VALUE, () => this.render(), { attribute: "value" });
|
|
27
|
+
/** Shows the number at the end of the track. */
|
|
28
|
+
showValue = this.useChange(false, (value) => {
|
|
29
|
+
this._refs.output.hidden = !value;
|
|
30
|
+
}, { attribute: "show-value" });
|
|
31
|
+
/** Ticks under the track: numbers, or `{ value, label }` for a tick with a label. */
|
|
32
|
+
marks = this.useChange([], () => this.renderMarks(), {
|
|
33
|
+
attribute: "marks",
|
|
34
|
+
parse: jsonOf([])
|
|
35
|
+
});
|
|
36
|
+
/** The slider's name for screen readers, when no visible label names it. */
|
|
37
|
+
label = this.useChange("", (value) => setOrRemove(this._refs.native, "aria-label", value), { attribute: "label" });
|
|
38
|
+
disabled = this.useChange(false, (value) => {
|
|
39
|
+
this.reflect("disabled", value);
|
|
40
|
+
this.renderDisabled();
|
|
41
|
+
}, { attribute: "disabled" });
|
|
42
|
+
_form = { disabled: false };
|
|
43
|
+
_refs = this.useRefs((ref) => ({
|
|
44
|
+
marks: ref(".marks"),
|
|
45
|
+
native: ref("input"),
|
|
46
|
+
output: ref(".output")
|
|
47
|
+
}));
|
|
48
|
+
focus(options) {
|
|
49
|
+
this._refs.native.focus(options);
|
|
50
|
+
}
|
|
51
|
+
templateHtml() {
|
|
52
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
53
|
+
class: "slider",
|
|
54
|
+
attrs: { part: "base" },
|
|
55
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
56
|
+
class: "track-area",
|
|
57
|
+
children: [/* @__PURE__ */ jsx("input", {
|
|
58
|
+
type: "range",
|
|
59
|
+
class: "native"
|
|
60
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
61
|
+
class: "marks",
|
|
62
|
+
"aria-hidden": "true",
|
|
63
|
+
hidden: true
|
|
64
|
+
})]
|
|
65
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
66
|
+
class: "output",
|
|
67
|
+
"aria-hidden": "true",
|
|
68
|
+
hidden: true
|
|
69
|
+
})]
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
templateCss() {
|
|
73
|
+
return css`${BASE_STYLES}${jl_slider_default}`;
|
|
74
|
+
}
|
|
75
|
+
onConnect() {
|
|
76
|
+
const native = this._refs.native;
|
|
77
|
+
this.on(native, "input", (event) => {
|
|
78
|
+
event.stopPropagation();
|
|
79
|
+
this.value.set(native.valueAsNumber);
|
|
80
|
+
this.events.emit("input", native.valueAsNumber);
|
|
81
|
+
});
|
|
82
|
+
this.on(native, "change", () => this.events.emit("change", native.valueAsNumber));
|
|
83
|
+
}
|
|
84
|
+
resetValue() {
|
|
85
|
+
this.value.set(parseNumber(this.getAttribute("value")) ?? DEFAULT_VALUE);
|
|
86
|
+
}
|
|
87
|
+
/** The browser calls it for a disabled fieldset and for the element's own disabled attribute, even before render. */
|
|
88
|
+
setDisabledByForm(disabled) {
|
|
89
|
+
this._form.disabled = disabled;
|
|
90
|
+
this.whenRendered(() => this.renderDisabled());
|
|
91
|
+
}
|
|
92
|
+
renderDisabled() {
|
|
93
|
+
this._refs.native.disabled = this.disabled.get() || this._form.disabled;
|
|
94
|
+
}
|
|
95
|
+
render() {
|
|
96
|
+
const native = this._refs.native;
|
|
97
|
+
native.min = String(this.min.get());
|
|
98
|
+
native.max = String(this.max.get());
|
|
99
|
+
native.step = String(this.step.get());
|
|
100
|
+
native.value = String(this.value.get());
|
|
101
|
+
if (native.valueAsNumber !== this.value.get()) {
|
|
102
|
+
this.value.set(native.valueAsNumber);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
this.renderPosition();
|
|
106
|
+
}
|
|
107
|
+
/** New bounds move the thumb and the marks. */
|
|
108
|
+
renderRange() {
|
|
109
|
+
this.render();
|
|
110
|
+
this.renderMarks();
|
|
111
|
+
}
|
|
112
|
+
/** The fill, the shown number and the form's value, from the value the native input kept. */
|
|
113
|
+
renderPosition() {
|
|
114
|
+
const native = this._refs.native;
|
|
115
|
+
const fraction = fractionOf(native.valueAsNumber, this.min.get(), this.max.get());
|
|
116
|
+
native.style.setProperty("--fraction", String(fraction));
|
|
117
|
+
this._refs.output.textContent = native.value;
|
|
118
|
+
this.internals.setFormValue(native.value);
|
|
119
|
+
}
|
|
120
|
+
renderMarks() {
|
|
121
|
+
const min = this.min.get();
|
|
122
|
+
const max = this.max.get();
|
|
123
|
+
const marks = marksOf(this.marks.get(), min, max);
|
|
124
|
+
const container = this._refs.marks;
|
|
125
|
+
container.hidden = marks.length === 0;
|
|
126
|
+
this.reflect("has-labels", marks.some((mark) => mark.label !== void 0));
|
|
127
|
+
container.replaceChildren(...marks.map((mark) => {
|
|
128
|
+
const element = /* @__PURE__ */ jsxs("span", {
|
|
129
|
+
class: "mark",
|
|
130
|
+
children: [/* @__PURE__ */ jsx("span", { class: "tick" }), mark.label === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
131
|
+
class: "mark-label",
|
|
132
|
+
children: mark.label
|
|
133
|
+
})]
|
|
134
|
+
});
|
|
135
|
+
const fraction = fractionOf(mark.value, min, max);
|
|
136
|
+
element.style.setProperty("--at", String(fraction));
|
|
137
|
+
setOrRemove(element, "data-edge", EDGES.get(fraction) ?? "");
|
|
138
|
+
return element;
|
|
139
|
+
}));
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
JlSlider.register();
|
|
143
|
+
export { JlSlider };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// src/atoms/jl-spinner.css?raw
|
|
2
|
+
var jl_spinner_default = ":host {\n display: inline-flex;\n flex: none;\n --size: 16px;\n}\n\n.ring {\n width: var(--size);\n height: var(--size);\n border: 2px solid color-mix(in srgb, currentColor 22%, transparent);\n border-top-color: currentColor;\n border-radius: 50%;\n animation: spin 0.7s linear infinite;\n}\n\n@keyframes spin {\n to {\n transform: rotate(1turn);\n }\n}\n\n/* The one animation reduced motion keeps, slower: a still ring would read as stuck. */\n@media (prefers-reduced-motion: reduce) {\n .ring {\n /* biome-ignore lint/complexity/noImportantStyles: wins over the reduced-motion rule of BASE_STYLES */\n animation-duration: 1.6s !important;\n /* biome-ignore lint/complexity/noImportantStyles: wins over the reduced-motion rule of BASE_STYLES */\n animation-iteration-count: infinite !important;\n }\n}\n";
|
|
3
|
+
export { jl_spinner_default as default };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { JlElement } from '../base/jl-element';
|
|
2
|
+
/** A turning ring for work in progress. It follows the text colour; `label` is what screen readers say. */
|
|
3
|
+
export declare class JlSpinner extends JlElement {
|
|
4
|
+
static readonly selector = "jl-spinner";
|
|
5
|
+
readonly size: Readonly<Readonly<{
|
|
6
|
+
get(): number;
|
|
7
|
+
set(setter: number | ((prevState: number) => number)): void;
|
|
8
|
+
}>>;
|
|
9
|
+
readonly label: Readonly<Readonly<{
|
|
10
|
+
get(): string;
|
|
11
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
12
|
+
}>>;
|
|
13
|
+
private readonly _refs;
|
|
14
|
+
templateHtml(): Node;
|
|
15
|
+
templateCss(): string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BASE_STYLES } from "../styles/shared.js";
|
|
2
|
+
import { JlElement } from "../base/jl-element.js";
|
|
3
|
+
import jl_spinner_default from "./jl-spinner.css_raw.js";
|
|
4
|
+
import { css } from "@jadis/core";
|
|
5
|
+
import { jsx } from "@jadis/core/jsx-runtime";
|
|
6
|
+
// src/atoms/jl-spinner.tsx
|
|
7
|
+
var DEFAULT_SIZE = 16;
|
|
8
|
+
var DEFAULT_LABEL = "Loading";
|
|
9
|
+
/** A turning ring for work in progress. It follows the text colour; `label` is what screen readers say. */
|
|
10
|
+
var JlSpinner = class extends JlElement {
|
|
11
|
+
static selector = "jl-spinner";
|
|
12
|
+
size = this.useChange(DEFAULT_SIZE, (value) => this.style.setProperty("--size", `${value}px`), { attribute: "size" });
|
|
13
|
+
label = this.useChange(DEFAULT_LABEL, (value) => this._refs.ring.setAttribute("aria-label", value), { attribute: "label" });
|
|
14
|
+
_refs = this.useRefs((ref) => ({ ring: ref(".ring") }));
|
|
15
|
+
templateHtml() {
|
|
16
|
+
return /* @__PURE__ */ jsx("span", {
|
|
17
|
+
class: "ring",
|
|
18
|
+
role: "status"
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
templateCss() {
|
|
22
|
+
return css`${BASE_STYLES}${jl_spinner_default}`;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
JlSpinner.register();
|
|
26
|
+
export { JlSpinner };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
// src/atoms/jl-switch.css?raw
|
|
2
|
+
var jl_switch_default = ":host {\n display: inline-flex;\n vertical-align: middle;\n --track-width: 36px;\n --track-height: 20px;\n --thumb: 14px;\n}\n\n:host([size=\"sm\"]) {\n --track-width: 28px;\n --track-height: 16px;\n --thumb: 10px;\n}\n\n.wrap {\n display: inline-flex;\n align-items: flex-start;\n gap: 10px;\n color: var(--jl-text);\n font-size: var(--jl-font-md);\n line-height: 20px;\n cursor: pointer;\n}\n\n:host([size=\"sm\"]) .wrap {\n font-size: var(--jl-font-sm);\n}\n\n.track {\n position: relative;\n display: inline-flex;\n flex: none;\n width: var(--track-width);\n height: var(--track-height);\n margin-top: calc((20px - var(--track-height)) / 2);\n}\n\n/* The native box keeps the semantics and the keyboard; it is drawn as the track, the thumb slides over it. */\n.native {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n margin: 0;\n border: 1px solid var(--jl-line-strong);\n border-radius: var(--jl-radius-pill);\n background: var(--jl-surface-3);\n cursor: inherit;\n appearance: none;\n transition:\n background var(--jl-fast) var(--jl-ease),\n border-color var(--jl-fast) var(--jl-ease),\n box-shadow var(--jl-fast) var(--jl-ease);\n}\n\n.wrap:hover .native:not(:disabled) {\n border-color: color-mix(in srgb, var(--jl-line-strong) 60%, var(--jl-text) 18%);\n}\n\n.native:checked {\n border-color: var(--jl-accent);\n background: var(--jl-accent);\n}\n\n.wrap:hover .native:checked:not(:disabled) {\n border-color: var(--jl-accent-strong);\n background: var(--jl-accent-strong);\n}\n\n.thumb {\n position: absolute;\n top: calc((var(--track-height) - var(--thumb)) / 2);\n left: calc((var(--track-height) - var(--thumb)) / 2);\n width: var(--thumb);\n height: var(--thumb);\n border-radius: 50%;\n background: var(--jl-muted);\n pointer-events: none;\n transition:\n transform var(--jl-fast) var(--jl-ease),\n background var(--jl-fast) var(--jl-ease);\n}\n\n.native:checked + .thumb {\n background: var(--jl-on-accent);\n transform: translateX(calc(var(--track-width) - var(--track-height)));\n}\n\n/* Its baseline is the element's, so a label beside it (a horizontal field) lines up with the text. */\n.text {\n display: grid;\n align-self: baseline;\n gap: 2px;\n}\n\n.description {\n color: var(--jl-muted);\n font-size: var(--jl-font-sm);\n line-height: 18px;\n}\n\n:host([disabled]) .wrap,\n:host(:disabled) .wrap {\n cursor: not-allowed;\n opacity: 0.5;\n}\n";
|
|
3
|
+
export { jl_switch_default as default };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { JlFormControl } from '../base/jl-form-control';
|
|
2
|
+
import type { SwitchSize } from '../types/jl-switch.types';
|
|
3
|
+
export declare const SWITCH_SIZES: readonly SwitchSize[];
|
|
4
|
+
/**
|
|
5
|
+
* An on/off setting that applies at once, such as "Dark mode" or "Email me". `checked` is the state; the form gets
|
|
6
|
+
* `value` while it is on. For a choice confirmed later with a button, prefer a checkbox.
|
|
7
|
+
*/
|
|
8
|
+
export declare class JlSwitch extends JlFormControl {
|
|
9
|
+
static readonly selector = "jl-switch";
|
|
10
|
+
readonly events: Readonly<import("@jadis/core").UseEventsHandler<{
|
|
11
|
+
change: boolean;
|
|
12
|
+
}>>;
|
|
13
|
+
readonly checked: Readonly<Readonly<{
|
|
14
|
+
get(): boolean;
|
|
15
|
+
set(setter: boolean | ((prevState: boolean) => boolean)): void;
|
|
16
|
+
}>>;
|
|
17
|
+
/** The text beside the switch. */
|
|
18
|
+
readonly label: Readonly<Readonly<{
|
|
19
|
+
get(): string;
|
|
20
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
21
|
+
}>>;
|
|
22
|
+
/** A smaller line under the label. */
|
|
23
|
+
readonly description: Readonly<Readonly<{
|
|
24
|
+
get(): string;
|
|
25
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
26
|
+
}>>;
|
|
27
|
+
readonly size: Readonly<Readonly<{
|
|
28
|
+
get(): SwitchSize;
|
|
29
|
+
set(setter: ((prevState: SwitchSize) => SwitchSize) | SwitchSize): void;
|
|
30
|
+
}>>;
|
|
31
|
+
/** What the form gets while the switch is on. */
|
|
32
|
+
readonly value: Readonly<Readonly<{
|
|
33
|
+
get(): string;
|
|
34
|
+
set(setter: string | ((prevState: string) => string)): void;
|
|
35
|
+
}>>;
|
|
36
|
+
readonly disabled: Readonly<Readonly<{
|
|
37
|
+
get(): boolean;
|
|
38
|
+
set(setter: boolean | ((prevState: boolean) => boolean)): void;
|
|
39
|
+
}>>;
|
|
40
|
+
private readonly _form;
|
|
41
|
+
private readonly _refs;
|
|
42
|
+
focus(options?: FocusOptions): void;
|
|
43
|
+
/** Flips the state, as a click would, and fires `change`. */
|
|
44
|
+
toggle(): void;
|
|
45
|
+
templateHtml(): Node;
|
|
46
|
+
templateCss(): string;
|
|
47
|
+
onConnect(): void;
|
|
48
|
+
protected resetValue(): void;
|
|
49
|
+
/** The browser calls it for a disabled fieldset and for the element's own disabled attribute, even before render. */
|
|
50
|
+
protected setDisabledByForm(disabled: boolean): void;
|
|
51
|
+
private renderDisabled;
|
|
52
|
+
private commit;
|
|
53
|
+
private renderChecked;
|
|
54
|
+
private renderFormValue;
|
|
55
|
+
/** Hides the text column when there is nothing to show, so a lone switch has no gap beside it. */
|
|
56
|
+
private renderText;
|
|
57
|
+
}
|