@fairfox/polly 0.77.3 → 0.79.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/cli/polly.js +46 -3
- package/dist/cli/polly.js.map +3 -3
- package/dist/src/background/index.js.map +3 -3
- package/dist/src/background/message-router.js.map +3 -3
- package/dist/src/client/index.js +137 -32
- package/dist/src/client/index.js.map +6 -5
- package/dist/src/client/wrapper.d.ts +39 -2
- package/dist/src/elysia/index.js +22 -3
- package/dist/src/elysia/index.js.map +5 -5
- package/dist/src/elysia/route-match.d.ts +13 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +12 -2
- package/dist/src/index.js.map +7 -7
- package/dist/src/mesh.js +87 -46
- package/dist/src/mesh.js.map +12 -11
- package/dist/src/peer.js +7 -3
- package/dist/src/peer.js.map +6 -6
- package/dist/src/polly-ui/Badge.d.ts +5 -0
- package/dist/src/polly-ui/Button.d.ts +31 -6
- package/dist/src/polly-ui/Dropdown.d.ts +6 -0
- package/dist/src/polly-ui/Select.d.ts +11 -1
- package/dist/src/polly-ui/TextInput.d.ts +30 -0
- package/dist/src/polly-ui/index.css +10 -0
- package/dist/src/polly-ui/index.js +81 -32
- package/dist/src/polly-ui/index.js.map +10 -10
- package/dist/src/polly-ui/styles.css +10 -0
- package/dist/src/shared/adapters/index.js.map +3 -3
- package/dist/src/shared/lib/context-helpers.js.map +3 -3
- package/dist/src/shared/lib/mesh-client.d.ts +38 -0
- package/dist/src/shared/lib/mesh-signaling-client.d.ts +6 -5
- package/dist/src/shared/lib/mesh-state.d.ts +21 -0
- package/dist/src/shared/lib/message-bus.js.map +3 -3
- package/dist/src/shared/lib/peer-relay-adapter.d.ts +5 -0
- package/dist/src/shared/lib/peer-repo-server.d.ts +15 -0
- package/dist/src/shared/lib/resource.js +11 -2
- package/dist/src/shared/lib/resource.js.map +6 -6
- package/dist/src/shared/lib/state.d.ts +20 -0
- package/dist/src/shared/lib/state.js +11 -1
- package/dist/src/shared/lib/state.js.map +5 -5
- package/dist/src/shared/state/app-state.js +10 -1
- package/dist/src/shared/state/app-state.js.map +5 -5
- package/dist/tools/init/src/cli.js +23 -2
- package/dist/tools/init/src/cli.js.map +4 -4
- package/dist/tools/init/templates/pwa/package.json.template +1 -1
- package/dist/tools/init/templates/pwa/src/service-worker.ts.template +26 -15
- package/dist/tools/init/templates/pwa/src/shared-worker.ts.template +13 -3
- package/dist/tools/init/templates/pwa/tsconfig.json.template +2 -2
- package/dist/tools/init/templates/pwa/tsconfig.worker.json.template +17 -0
- package/dist/tools/test/src/browser/index.js +5 -2
- package/dist/tools/test/src/browser/index.js.map +3 -3
- package/dist/tools/test/src/contrast/index.js +20 -15
- package/dist/tools/test/src/contrast/index.js.map +3 -3
- package/dist/tools/test/src/e2e-cli/index.d.ts +10 -0
- package/dist/tools/test/src/e2e-cli/run-cli.d.ts +25 -0
- package/dist/tools/test/src/e2e-cli/with-temp-dir.d.ts +15 -0
- package/dist/tools/test/src/e2e-mesh/index.js +12 -7
- package/dist/tools/test/src/e2e-mesh/index.js.map +4 -4
- package/dist/tools/test/src/e2e-mesh/launch-peer.d.ts +7 -1
- package/dist/tools/test/src/e2e-relay/index.d.ts +12 -0
- package/dist/tools/test/src/e2e-relay/wait-for-relay-convergence.d.ts +27 -0
- package/dist/tools/test/src/e2e-relay/with-repo-server.d.ts +24 -0
- package/dist/tools/test/src/e2e-shared/assert.d.ts +18 -0
- package/dist/tools/test/src/e2e-shared/contract.d.ts +40 -0
- package/dist/tools/test/src/e2e-shared/index.d.ts +2 -0
- package/dist/tools/test/src/tiers/args.d.ts +23 -0
- package/dist/tools/test/src/tiers/cli.d.ts +2 -0
- package/dist/tools/test/src/tiers/cli.js +490 -0
- package/dist/tools/test/src/tiers/cli.js.map +16 -0
- package/dist/tools/test/src/tiers/detect.d.ts +12 -0
- package/dist/tools/test/src/tiers/discover.d.ts +2 -0
- package/dist/tools/test/src/tiers/engine.d.ts +3 -0
- package/dist/tools/test/src/tiers/index.d.ts +14 -0
- package/dist/tools/test/src/tiers/protocol.d.ts +10 -0
- package/dist/tools/test/src/tiers/reporter.d.ts +12 -0
- package/dist/tools/test/src/tiers/types.d.ts +94 -0
- package/dist/tools/test/src/tiers/worker.d.ts +2 -0
- package/dist/tools/test/src/tiers/worker.js +60 -0
- package/dist/tools/test/src/tiers/worker.js.map +12 -0
- package/dist/tools/verify/src/cli.js +322 -27
- package/dist/tools/verify/src/cli.js.map +13 -10
- package/dist/tools/verify/src/config.d.ts +10 -0
- package/dist/tools/verify/src/config.js.map +2 -2
- package/dist/tools/verify/src/stryker/index.js +20 -11
- package/dist/tools/verify/src/stryker/index.js.map +3 -3
- package/dist/tools/visualize/src/cli.js +8 -5
- package/dist/tools/visualize/src/cli.js.map +4 -4
- package/package.json +16 -6
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* from the `--polly-status-*` token family. The default variant uses
|
|
6
6
|
* surface-sunken + muted text for a neutral pill. Consumers style
|
|
7
7
|
* placement via className; the primitive owns size, shape, and colour.
|
|
8
|
+
*
|
|
9
|
+
* A badge is often an abbreviated or iconic status ("3", "●"); pass
|
|
10
|
+
* `title` to attach an explanatory hover tooltip ("3 peers connected").
|
|
8
11
|
*/
|
|
9
12
|
import type { ComponentChildren, JSX } from "preact";
|
|
10
13
|
export type BadgeVariant = "default" | "info" | "success" | "warning" | "danger";
|
|
@@ -13,5 +16,7 @@ export type BadgeProps = {
|
|
|
13
16
|
variant?: BadgeVariant;
|
|
14
17
|
className?: string;
|
|
15
18
|
id?: string;
|
|
19
|
+
/** Native hover tooltip — explains an abbreviated or iconic badge. */
|
|
20
|
+
title?: string;
|
|
16
21
|
};
|
|
17
22
|
export declare function Badge(props: BadgeProps): JSX.Element;
|
|
@@ -7,9 +7,18 @@
|
|
|
7
7
|
* size picks the padding + font scale (small/normal/large). Icon +
|
|
8
8
|
* label are arranged with a nested inline <Layout>.
|
|
9
9
|
*
|
|
10
|
+
* A text `label` is the accessible name. An icon-only button (icon, no
|
|
11
|
+
* label) has none, so the type REQUIRES `aria-label` there — an unnamed
|
|
12
|
+
* icon button won't compile. No build-time lint needed; the call site
|
|
13
|
+
* itself is the gate.
|
|
14
|
+
*
|
|
10
15
|
* Action wiring is declared via data-* attributes consumed by the
|
|
11
16
|
* global event delegator in @fairfox/polly/actions — Button does not
|
|
12
17
|
* accept an onClick prop.
|
|
18
|
+
*
|
|
19
|
+
* Every button surfaces a native hover tooltip: an explicit `title`
|
|
20
|
+
* wins, else the visible text label, else the `aria-label` (so an
|
|
21
|
+
* icon-only button still gets one). Pass `title=""` to suppress it.
|
|
13
22
|
*/
|
|
14
23
|
import type { ComponentChildren, JSX, VNode } from "preact";
|
|
15
24
|
export type ButtonTier = "primary" | "secondary" | "tertiary";
|
|
@@ -29,10 +38,7 @@ type BaseButtonProps = {
|
|
|
29
38
|
bounded?: boolean;
|
|
30
39
|
className?: string;
|
|
31
40
|
title?: string;
|
|
32
|
-
icon?: VNode;
|
|
33
|
-
label: ComponentChildren;
|
|
34
41
|
"data-action"?: string;
|
|
35
|
-
"aria-label"?: string;
|
|
36
42
|
/** Additional action-payload attributes the event delegator parses
|
|
37
43
|
* into `ctx.data`. `data-action-tid="t-17"` becomes `{ tid: "t-17" }`,
|
|
38
44
|
* `data-action-item-id="…"` becomes `{ itemId: "…" }`, and so on.
|
|
@@ -40,14 +46,33 @@ type BaseButtonProps = {
|
|
|
40
46
|
* consumer cares about type-checks without a Button-side enumeration. */
|
|
41
47
|
[actionDataAttr: `data-action-${string}`]: string | undefined;
|
|
42
48
|
};
|
|
43
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Content/accessibility dimension. A visible text `label` is the
|
|
51
|
+
* accessible name, so it makes `aria-label` optional. An icon-only
|
|
52
|
+
* button has no text to name it, so `aria-label` is REQUIRED — you
|
|
53
|
+
* cannot construct an unnamed icon button. (Button's hover title then
|
|
54
|
+
* falls back to that aria-label, so the same prop gives both the
|
|
55
|
+
* accessible name and the tooltip.)
|
|
56
|
+
*/
|
|
57
|
+
type LabelledContent = {
|
|
58
|
+
label: ComponentChildren;
|
|
59
|
+
icon?: VNode;
|
|
60
|
+
"aria-label"?: string;
|
|
61
|
+
};
|
|
62
|
+
type IconOnlyContent = {
|
|
63
|
+
icon: VNode;
|
|
64
|
+
label?: never;
|
|
65
|
+
"aria-label": string;
|
|
66
|
+
};
|
|
67
|
+
type ButtonContent = LabelledContent | IconOnlyContent;
|
|
68
|
+
type ButtonElement = {
|
|
44
69
|
href?: never;
|
|
45
70
|
target?: never;
|
|
46
71
|
rel?: never;
|
|
47
72
|
download?: never;
|
|
48
73
|
type?: "button" | "submit" | "reset";
|
|
49
74
|
};
|
|
50
|
-
type
|
|
75
|
+
type LinkElement = {
|
|
51
76
|
href: string;
|
|
52
77
|
target?: string;
|
|
53
78
|
rel?: string;
|
|
@@ -56,6 +81,6 @@ type ButtonAsLink = BaseButtonProps & {
|
|
|
56
81
|
download?: string;
|
|
57
82
|
type?: never;
|
|
58
83
|
};
|
|
59
|
-
export type ButtonProps =
|
|
84
|
+
export type ButtonProps = BaseButtonProps & ButtonContent & (ButtonElement | LinkElement);
|
|
60
85
|
export declare function Button(props: ButtonProps): JSX.Element;
|
|
61
86
|
export {};
|
|
@@ -35,6 +35,12 @@ export type DropdownProps = {
|
|
|
35
35
|
triggerClassName?: string;
|
|
36
36
|
/** Disables the trigger <button>. */
|
|
37
37
|
triggerDisabled?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Native hover tooltip on the trigger <button>. Select/ActionSelect
|
|
40
|
+
* pass the current selection so a truncated trigger still reveals its
|
|
41
|
+
* full value on hover.
|
|
42
|
+
*/
|
|
43
|
+
triggerTitle?: string;
|
|
38
44
|
id?: string;
|
|
39
45
|
};
|
|
40
46
|
export declare function Dropdown(props: DropdownProps): JSX.Element;
|
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* row for multi-select. The `selected` state is a Signal<Set<T>>;
|
|
6
6
|
* single-select replaces the set, multi-select toggles membership.
|
|
7
7
|
* Multi-select mode also shows Select All / Clear action buttons at
|
|
8
|
-
* the top of the menu.
|
|
8
|
+
* the top of the menu. Single-select mode can opt into `clearable`,
|
|
9
|
+
* which prepends a placeholder-labelled option that returns the
|
|
10
|
+
* selection to empty — for "Any …" filter semantics.
|
|
9
11
|
*/
|
|
10
12
|
import { type Signal } from "@preact/signals";
|
|
11
13
|
import type { JSX } from "preact";
|
|
@@ -19,6 +21,14 @@ export type SelectProps<T = string> = {
|
|
|
19
21
|
label?: string;
|
|
20
22
|
placeholder?: string;
|
|
21
23
|
multiSelect?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Single-select only: prepend an option labelled with the placeholder
|
|
26
|
+
* that returns the selection to empty. Without it, picking an option
|
|
27
|
+
* is a trap — nothing in the list leads back to "any". Use it for
|
|
28
|
+
* optional filters ("Any stage"), not required form fields
|
|
29
|
+
* ("Select a team"). Ignored in multi-select, which has Clear.
|
|
30
|
+
*/
|
|
31
|
+
clearable?: boolean;
|
|
22
32
|
disabled?: boolean;
|
|
23
33
|
/** Apply a comfortable minimum width to the trigger. Default: sizes to content. */
|
|
24
34
|
wide?: boolean;
|
|
@@ -7,17 +7,47 @@
|
|
|
7
7
|
* wired by the shared input-base, the stable `[data-polly-input]` hook
|
|
8
8
|
* is applied for styling, and `invalid` flips `aria-invalid` and
|
|
9
9
|
* `data-state="invalid"` for consumer selectors.
|
|
10
|
+
*
|
|
11
|
+
* `inputType` sets the native single-line input type — "text" (default),
|
|
12
|
+
* "email", "number", "date", and friends — so the browser supplies the
|
|
13
|
+
* right keyboard and validation. `min`/`max`/`step` apply to the
|
|
14
|
+
* single-line variant (e.g. numeric or date bounds) and keep filter
|
|
15
|
+
* fields from being unvalidated free text.
|
|
16
|
+
*
|
|
17
|
+
* `error`, when supplied, renders a message beneath the field, wraps the
|
|
18
|
+
* control in a labelled group, and auto-wires `aria-describedby` plus the
|
|
19
|
+
* invalid state — no manual id juggling. Without `error` the primitive
|
|
20
|
+
* stays a bare native element, exactly as before, so consumers that own
|
|
21
|
+
* their own surrounding structure are unaffected.
|
|
10
22
|
*/
|
|
11
23
|
import type { Signal } from "@preact/signals";
|
|
12
24
|
import type { JSX } from "preact";
|
|
13
25
|
type Variant = "single" | "multi";
|
|
26
|
+
/** Native single-line input types polly's filter/form fields use. */
|
|
27
|
+
export type TextInputType = "text" | "email" | "url" | "tel" | "search" | "password" | "number" | "date" | "datetime-local" | "time" | "month" | "week";
|
|
14
28
|
export type TextInputProps = {
|
|
15
29
|
name: string;
|
|
16
30
|
/** Signal<string> for controlled, string for uncontrolled default. */
|
|
17
31
|
value?: Signal<string> | string;
|
|
18
32
|
variant?: Variant;
|
|
33
|
+
/** Native input type for the single-line variant. Default: "text". */
|
|
34
|
+
inputType?: TextInputType;
|
|
35
|
+
/** Lower bound for the single-line variant (number/date types). */
|
|
36
|
+
min?: number | string;
|
|
37
|
+
/** Upper bound for the single-line variant (number/date types). */
|
|
38
|
+
max?: number | string;
|
|
39
|
+
/** Step granularity for the single-line variant (number/date types). */
|
|
40
|
+
step?: number | string;
|
|
19
41
|
placeholder?: string;
|
|
42
|
+
/** Native hover tooltip — a hint beyond the placeholder/label. */
|
|
43
|
+
title?: string;
|
|
20
44
|
invalid?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Validation message rendered beneath the field. When present the
|
|
47
|
+
* primitive wraps the control, links the message via aria-describedby,
|
|
48
|
+
* and marks the field invalid. Omit it to keep a bare native element.
|
|
49
|
+
*/
|
|
50
|
+
error?: string;
|
|
21
51
|
required?: boolean;
|
|
22
52
|
disabled?: boolean;
|
|
23
53
|
readOnly?: boolean;
|
|
@@ -1033,6 +1033,16 @@
|
|
|
1033
1033
|
resize: vertical;
|
|
1034
1034
|
max-block-size: 40em;
|
|
1035
1035
|
}
|
|
1036
|
+
|
|
1037
|
+
.field_ez4_Vg {
|
|
1038
|
+
display: grid;
|
|
1039
|
+
gap: var(--polly-space-xs);
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
.error_ez4_Vg {
|
|
1043
|
+
font-size: var(--polly-text-sm);
|
|
1044
|
+
color: var(--polly-danger);
|
|
1045
|
+
}
|
|
1036
1046
|
}
|
|
1037
1047
|
|
|
1038
1048
|
/* src/polly-ui/Toast.module.css */
|
|
@@ -407,6 +407,7 @@ function Dropdown(props) {
|
|
|
407
407
|
className,
|
|
408
408
|
triggerClassName,
|
|
409
409
|
triggerDisabled = false,
|
|
410
|
+
triggerTitle,
|
|
410
411
|
id
|
|
411
412
|
} = props;
|
|
412
413
|
const menuRef = useRef2(null);
|
|
@@ -469,7 +470,7 @@ function Dropdown(props) {
|
|
|
469
470
|
menu.style.top = `${top}px`;
|
|
470
471
|
};
|
|
471
472
|
const onBeforeToggle = (e) => {
|
|
472
|
-
if (e.newState === "open") {
|
|
473
|
+
if ("newState" in e && e.newState === "open") {
|
|
473
474
|
positionMenu();
|
|
474
475
|
}
|
|
475
476
|
};
|
|
@@ -525,6 +526,7 @@ function Dropdown(props) {
|
|
|
525
526
|
type: "button",
|
|
526
527
|
class: triggerClassName ?? Dropdown_module_default["trigger"] ?? "",
|
|
527
528
|
disabled: triggerDisabled,
|
|
529
|
+
title: triggerTitle,
|
|
528
530
|
"data-open": isOpen.value ? "true" : "false",
|
|
529
531
|
children: trigger
|
|
530
532
|
}, undefined, false, undefined, this),
|
|
@@ -532,6 +534,7 @@ function Dropdown(props) {
|
|
|
532
534
|
ref: menuRef,
|
|
533
535
|
id: popoverId,
|
|
534
536
|
role: "listbox",
|
|
537
|
+
"aria-multiselectable": multiSelect ? "true" : undefined,
|
|
535
538
|
class: Dropdown_module_default["menu"] ?? "",
|
|
536
539
|
"data-align": align,
|
|
537
540
|
popover: "auto",
|
|
@@ -621,6 +624,7 @@ function ActionSelect(props) {
|
|
|
621
624
|
disabled ? /* @__PURE__ */ jsxDEV4("span", {
|
|
622
625
|
class: triggerClass,
|
|
623
626
|
"aria-disabled": "true",
|
|
627
|
+
title: displayText,
|
|
624
628
|
children: /* @__PURE__ */ jsxDEV4("span", {
|
|
625
629
|
class: Select_module_default["triggerLabel"],
|
|
626
630
|
children: displayText
|
|
@@ -628,6 +632,7 @@ function ActionSelect(props) {
|
|
|
628
632
|
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV4(Dropdown, {
|
|
629
633
|
isOpen,
|
|
630
634
|
triggerClassName: triggerClass,
|
|
635
|
+
triggerTitle: displayText,
|
|
631
636
|
trigger: /* @__PURE__ */ jsxDEV4(Fragment, {
|
|
632
637
|
children: [
|
|
633
638
|
/* @__PURE__ */ jsxDEV4("span", {
|
|
@@ -681,7 +686,7 @@ function variantClass(variant) {
|
|
|
681
686
|
return;
|
|
682
687
|
}
|
|
683
688
|
function Badge(props) {
|
|
684
|
-
const { children, variant = "default", className, id } = props;
|
|
689
|
+
const { children, variant = "default", className, id, title } = props;
|
|
685
690
|
const parts = [Badge_module_default["badge"]];
|
|
686
691
|
const v = variantClass(variant);
|
|
687
692
|
if (v)
|
|
@@ -690,6 +695,7 @@ function Badge(props) {
|
|
|
690
695
|
parts.push(className);
|
|
691
696
|
return /* @__PURE__ */ jsxDEV5("span", {
|
|
692
697
|
id,
|
|
698
|
+
title,
|
|
693
699
|
class: parts.join(" "),
|
|
694
700
|
"data-polly-ui": true,
|
|
695
701
|
"data-polly-badge": variant,
|
|
@@ -781,13 +787,14 @@ function Button(props) {
|
|
|
781
787
|
alignItems: "center",
|
|
782
788
|
children: [
|
|
783
789
|
icon,
|
|
784
|
-
/* @__PURE__ */ jsxDEV6("span", {
|
|
790
|
+
label !== undefined && /* @__PURE__ */ jsxDEV6("span", {
|
|
785
791
|
children: label
|
|
786
792
|
}, undefined, false, undefined, this)
|
|
787
793
|
]
|
|
788
794
|
}, undefined, true, undefined, this) : label;
|
|
789
795
|
const dataAction = props["data-action"];
|
|
790
796
|
const ariaLabel = props["aria-label"];
|
|
797
|
+
const resolvedTitle = title ?? (typeof label === "string" && label.length > 0 ? label : typeof ariaLabel === "string" ? ariaLabel : undefined);
|
|
791
798
|
const actionDataAttrs = {};
|
|
792
799
|
for (const key of Object.keys(props)) {
|
|
793
800
|
if (key.startsWith("data-action-")) {
|
|
@@ -801,7 +808,7 @@ function Button(props) {
|
|
|
801
808
|
return /* @__PURE__ */ jsxDEV6("a", {
|
|
802
809
|
id,
|
|
803
810
|
class: buttonClass,
|
|
804
|
-
title,
|
|
811
|
+
title: resolvedTitle,
|
|
805
812
|
href: disabled ? undefined : props.href,
|
|
806
813
|
target: "target" in props ? props.target : undefined,
|
|
807
814
|
rel: "rel" in props ? props.rel : undefined,
|
|
@@ -819,7 +826,7 @@ function Button(props) {
|
|
|
819
826
|
return /* @__PURE__ */ jsxDEV6("button", {
|
|
820
827
|
id,
|
|
821
828
|
class: buttonClass,
|
|
822
|
-
title,
|
|
829
|
+
title: resolvedTitle,
|
|
823
830
|
type: resolvedType,
|
|
824
831
|
disabled,
|
|
825
832
|
"aria-label": ariaLabel,
|
|
@@ -1802,6 +1809,7 @@ function Select(props) {
|
|
|
1802
1809
|
label,
|
|
1803
1810
|
placeholder = "Select…",
|
|
1804
1811
|
multiSelect = false,
|
|
1812
|
+
clearable = false,
|
|
1805
1813
|
disabled = false,
|
|
1806
1814
|
wide = false,
|
|
1807
1815
|
className,
|
|
@@ -1832,6 +1840,10 @@ function Select(props) {
|
|
|
1832
1840
|
const handleClear = () => {
|
|
1833
1841
|
selected.value = new Set;
|
|
1834
1842
|
};
|
|
1843
|
+
const handleClearOption = () => {
|
|
1844
|
+
selected.value = new Set;
|
|
1845
|
+
isOpen2.value = false;
|
|
1846
|
+
};
|
|
1835
1847
|
const triggerParts = [Select_module_default["trigger"] ?? ""];
|
|
1836
1848
|
if (isEmpty.value)
|
|
1837
1849
|
triggerParts.push(Select_module_default["placeholder"] ?? "");
|
|
@@ -1868,6 +1880,7 @@ function Select(props) {
|
|
|
1868
1880
|
trigger: triggerContent,
|
|
1869
1881
|
triggerClassName: triggerClass,
|
|
1870
1882
|
triggerDisabled: disabled,
|
|
1883
|
+
triggerTitle: displayText.value,
|
|
1871
1884
|
multiSelect,
|
|
1872
1885
|
children: [
|
|
1873
1886
|
multiSelect && /* @__PURE__ */ jsxDEV17("div", {
|
|
@@ -1891,11 +1904,24 @@ function Select(props) {
|
|
|
1891
1904
|
]
|
|
1892
1905
|
}, undefined, true, undefined, this)
|
|
1893
1906
|
}, undefined, false, undefined, this),
|
|
1907
|
+
!multiSelect && clearable && /* @__PURE__ */ jsxDEV17("button", {
|
|
1908
|
+
type: "button",
|
|
1909
|
+
role: "option",
|
|
1910
|
+
"aria-selected": isEmpty.value ? "true" : "false",
|
|
1911
|
+
class: isEmpty.value ? `${Select_module_default["option"]} ${Select_module_default["optionSelected"]}` : Select_module_default["option"],
|
|
1912
|
+
"data-polly-select-clear": true,
|
|
1913
|
+
onClick: handleClearOption,
|
|
1914
|
+
children: /* @__PURE__ */ jsxDEV17("span", {
|
|
1915
|
+
children: placeholder
|
|
1916
|
+
}, undefined, false, undefined, this)
|
|
1917
|
+
}, undefined, false, undefined, this),
|
|
1894
1918
|
options.map((opt) => {
|
|
1895
1919
|
const isSelected = selected.value.has(opt.value);
|
|
1896
1920
|
const optClass = isSelected ? `${Select_module_default["option"]} ${Select_module_default["optionSelected"]}` : Select_module_default["option"];
|
|
1897
1921
|
return /* @__PURE__ */ jsxDEV17("button", {
|
|
1898
1922
|
type: "button",
|
|
1923
|
+
role: "option",
|
|
1924
|
+
"aria-selected": isSelected ? "true" : "false",
|
|
1899
1925
|
class: optClass,
|
|
1900
1926
|
onClick: () => handleOptionClick(opt.value),
|
|
1901
1927
|
children: [
|
|
@@ -2070,6 +2096,9 @@ function Text(props) {
|
|
|
2070
2096
|
"data-polly-text": tone
|
|
2071
2097
|
}, children);
|
|
2072
2098
|
}
|
|
2099
|
+
// src/polly-ui/TextInput.tsx
|
|
2100
|
+
import { useId as useId2 } from "preact/hooks";
|
|
2101
|
+
|
|
2073
2102
|
// src/polly-ui/internal/input-base.ts
|
|
2074
2103
|
function buildInputA11y(props) {
|
|
2075
2104
|
const attrs = {
|
|
@@ -2091,7 +2120,9 @@ function buildInputA11y(props) {
|
|
|
2091
2120
|
|
|
2092
2121
|
// src/polly-ui/TextInput.module.css
|
|
2093
2122
|
var TextInput_module_default = {
|
|
2094
|
-
input: "input_ez4_Vg"
|
|
2123
|
+
input: "input_ez4_Vg",
|
|
2124
|
+
field: "field_ez4_Vg",
|
|
2125
|
+
error: "error_ez4_Vg"
|
|
2095
2126
|
};
|
|
2096
2127
|
|
|
2097
2128
|
// src/polly-ui/TextInput.tsx
|
|
@@ -2101,12 +2132,15 @@ function isSignal2(v) {
|
|
|
2101
2132
|
}
|
|
2102
2133
|
function TextInput(props) {
|
|
2103
2134
|
const variant = props.variant ?? "single";
|
|
2135
|
+
const errorId = useId2();
|
|
2136
|
+
const hasError = props.error !== undefined && props.error !== "";
|
|
2137
|
+
const describedBy = [props.describedBy, hasError ? errorId : undefined].filter(Boolean).join(" ") || undefined;
|
|
2104
2138
|
const a11y = buildInputA11y({
|
|
2105
2139
|
name: props.name,
|
|
2106
2140
|
id: props.id,
|
|
2107
2141
|
required: props.required,
|
|
2108
|
-
invalid: props.invalid,
|
|
2109
|
-
describedBy
|
|
2142
|
+
invalid: props.invalid || hasError,
|
|
2143
|
+
describedBy,
|
|
2110
2144
|
placeholder: props.placeholder,
|
|
2111
2145
|
disabled: props.disabled,
|
|
2112
2146
|
readOnly: props.readOnly
|
|
@@ -2115,36 +2149,51 @@ function TextInput(props) {
|
|
|
2115
2149
|
const stringValue = controlled ? props.value.value : undefined;
|
|
2116
2150
|
const defaultValue = controlled ? undefined : props.value ?? "";
|
|
2117
2151
|
const className = props.className ? `${TextInput_module_default["input"]} ${props.className}` : TextInput_module_default["input"];
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
}
|
|
2134
|
-
return /* @__PURE__ */ jsxDEV20("input", {
|
|
2152
|
+
const onInput = (e) => {
|
|
2153
|
+
if (controlled) {
|
|
2154
|
+
props.value.value = e.currentTarget.value;
|
|
2155
|
+
}
|
|
2156
|
+
};
|
|
2157
|
+
const control = variant === "multi" ? /* @__PURE__ */ jsxDEV20("textarea", {
|
|
2158
|
+
...a11y,
|
|
2159
|
+
class: className,
|
|
2160
|
+
title: props.title,
|
|
2161
|
+
"data-polly-input-variant": "multi",
|
|
2162
|
+
rows: props.rows,
|
|
2163
|
+
autoFocus: props.autoFocus,
|
|
2164
|
+
value: stringValue,
|
|
2165
|
+
defaultValue,
|
|
2166
|
+
onInput
|
|
2167
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV20("input", {
|
|
2135
2168
|
...a11y,
|
|
2136
|
-
type: "text",
|
|
2169
|
+
type: props.inputType ?? "text",
|
|
2137
2170
|
class: className,
|
|
2171
|
+
title: props.title,
|
|
2138
2172
|
"data-polly-input-variant": "single",
|
|
2173
|
+
min: props.min,
|
|
2174
|
+
max: props.max,
|
|
2175
|
+
step: props.step,
|
|
2139
2176
|
autoFocus: props.autoFocus,
|
|
2140
2177
|
value: stringValue,
|
|
2141
2178
|
defaultValue,
|
|
2142
|
-
onInput
|
|
2143
|
-
if (controlled) {
|
|
2144
|
-
props.value.value = e.currentTarget.value;
|
|
2145
|
-
}
|
|
2146
|
-
}
|
|
2179
|
+
onInput
|
|
2147
2180
|
}, undefined, false, undefined, this);
|
|
2181
|
+
if (!hasError)
|
|
2182
|
+
return control;
|
|
2183
|
+
return /* @__PURE__ */ jsxDEV20("div", {
|
|
2184
|
+
class: TextInput_module_default["field"],
|
|
2185
|
+
"data-polly-ui": true,
|
|
2186
|
+
"data-polly-field": true,
|
|
2187
|
+
children: [
|
|
2188
|
+
control,
|
|
2189
|
+
/* @__PURE__ */ jsxDEV20("span", {
|
|
2190
|
+
id: errorId,
|
|
2191
|
+
role: "alert",
|
|
2192
|
+
class: TextInput_module_default["error"],
|
|
2193
|
+
children: props.error
|
|
2194
|
+
}, undefined, false, undefined, this)
|
|
2195
|
+
]
|
|
2196
|
+
}, undefined, true, undefined, this);
|
|
2148
2197
|
}
|
|
2149
2198
|
// src/polly-ui/Toast.tsx
|
|
2150
2199
|
import { createPortal as createPortal2 } from "preact/compat";
|
|
@@ -2335,4 +2384,4 @@ export {
|
|
|
2335
2384
|
ActionForm
|
|
2336
2385
|
};
|
|
2337
2386
|
|
|
2338
|
-
//# debugId=
|
|
2387
|
+
//# debugId=0625A7B5727F691364756E2164756E21
|