@antadesign/anta 0.3.34 → 0.3.35
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.md +14 -1
- package/README.md +9 -0
- package/dist/anta_helpers.d.ts +46 -30
- package/dist/anta_helpers.js +66 -25
- package/dist/bundle.css +1 -1
- package/dist/bundle.js +2 -1333
- package/dist/components/Banner.d.ts +25 -40
- package/dist/components/Banner.js +15 -17
- package/dist/components/Button.js +1 -0
- package/dist/components/ButtonCopy.js +3 -2
- package/dist/components/Calendar.js +13 -13
- package/dist/components/Card.d.ts +9 -17
- package/dist/components/Card.js +50 -46
- package/dist/components/Dialog.d.ts +1 -0
- package/dist/components/Dialog.js +16 -10
- package/dist/components/Expander.d.ts +6 -21
- package/dist/components/Expander.js +24 -23
- package/dist/components/Icon.d.ts +8 -14
- package/dist/components/Input.d.ts +77 -96
- package/dist/components/Input.js +23 -27
- package/dist/components/InputAutocomplete.d.ts +29 -10
- package/dist/components/InputAutocomplete.js +25 -8
- package/dist/components/InputDate.js +2 -2
- package/dist/components/InputTime.d.ts +10 -4
- package/dist/components/InputTime.js +20 -16
- package/dist/components/Loader.d.ts +2 -2
- package/dist/components/Menu.d.ts +5 -4
- package/dist/components/Menu.js +13 -8
- package/dist/components/MenuItem.js +1 -14
- package/dist/components/MenuItemCopy.js +2 -2
- package/dist/components/Panel.d.ts +3 -1
- package/dist/components/Panel.js +17 -11
- package/dist/components/Progress.d.ts +21 -23
- package/dist/components/Progress.js +13 -9
- package/dist/components/RadioGroup.js +6 -8
- package/dist/components/{select-parts.css → Select.css} +1 -1
- package/dist/components/Select.d.ts +53 -35
- package/dist/components/Select.js +53 -97
- package/dist/components/SelectFaceted.d.ts +7 -3
- package/dist/components/SelectFaceted.js +21 -9
- package/dist/components/Slider.d.ts +28 -11
- package/dist/components/Slider.js +20 -20
- package/dist/components/Steps.css +1 -1
- package/dist/components/Steps.js +1 -11
- package/dist/components/Tabs.d.ts +17 -20
- package/dist/components/Tabs.js +5 -8
- package/dist/components/Text.d.ts +55 -36
- package/dist/components/Text.js +35 -22
- package/dist/components/Title.d.ts +16 -26
- package/dist/components/Title.js +2 -1
- package/dist/components/Toaster.js +9 -2
- package/dist/components/Tooltip.d.ts +10 -15
- package/dist/components/copy-props.d.ts +14 -3
- package/dist/components/copy-props.js +14 -3
- package/dist/components/select-tree.d.ts +24 -0
- package/dist/components/select-tree.js +35 -0
- package/dist/element-base.d.ts +10 -0
- package/dist/element-base.js +15 -0
- package/dist/elements/a-banner.css +1 -1
- package/dist/elements/a-banner.d.ts +4 -1
- package/dist/elements/a-banner.js +22 -112
- package/dist/elements/a-button.d.ts +2 -1
- package/dist/elements/a-button.js +18 -1
- package/dist/elements/a-calendar.d.ts +14 -13
- package/dist/elements/a-calendar.js +29 -24
- package/dist/elements/a-card.css +1 -1
- package/dist/elements/a-card.d.ts +0 -9
- package/dist/elements/a-card.js +0 -184
- package/dist/elements/a-checkbox.css +1 -1
- package/dist/elements/a-copy.css +1 -1
- package/dist/elements/a-copy.d.ts +1 -5
- package/dist/elements/a-copy.js +129 -108
- package/dist/elements/a-dialog.css +1 -1
- package/dist/elements/a-dialog.d.ts +1 -1
- package/dist/elements/a-dialog.js +66 -194
- package/dist/elements/a-expander.css +1 -1
- package/dist/elements/a-expander.d.ts +4 -30
- package/dist/elements/a-expander.js +85 -344
- package/dist/elements/a-icon.d.ts +5 -23
- package/dist/elements/a-icon.js +1 -2
- package/dist/elements/a-input-time.css +1 -1
- package/dist/elements/a-input-time.d.ts +2 -1
- package/dist/elements/a-input-time.js +101 -168
- package/dist/elements/a-input.css +1 -1
- package/dist/elements/a-input.d.ts +10 -8
- package/dist/elements/a-input.js +155 -230
- package/dist/elements/a-loader.d.ts +5 -8
- package/dist/elements/a-loader.js +1 -2
- package/dist/elements/a-menu-item.css +1 -1
- package/dist/elements/a-menu-item.d.ts +5 -3
- package/dist/elements/a-menu-item.js +5 -1
- package/dist/elements/a-menu.css +1 -1
- package/dist/elements/a-menu.d.ts +5 -7
- package/dist/elements/a-menu.js +383 -299
- package/dist/elements/a-panel.css +1 -1
- package/dist/elements/a-panel.js +19 -37
- package/dist/elements/a-progress.css +1 -1
- package/dist/elements/a-progress.d.ts +0 -22
- package/dist/elements/a-progress.js +0 -100
- package/dist/elements/a-radio-group.d.ts +1 -1
- package/dist/elements/a-radio-group.js +6 -4
- package/dist/elements/a-select-faceted.d.ts +1 -1
- package/dist/elements/a-select-faceted.js +1 -1
- package/dist/elements/a-select.d.ts +1 -1
- package/dist/elements/a-select.js +1 -1
- package/dist/elements/a-slider.css +1 -1
- package/dist/elements/a-slider.d.ts +11 -3
- package/dist/elements/a-slider.js +244 -242
- package/dist/elements/a-switch.css +1 -1
- package/dist/elements/a-tab.css +1 -1
- package/dist/elements/a-tabs.css +1 -1
- package/dist/elements/a-tabs.d.ts +1 -1
- package/dist/elements/a-tabs.js +6 -4
- package/dist/elements/a-tag.css +1 -1
- package/dist/elements/a-text.css +1 -1
- package/dist/elements/a-text.d.ts +6 -43
- package/dist/elements/a-text.js +110 -193
- package/dist/elements/a-title.css +1 -1
- package/dist/elements/a-toast.css +1 -1
- package/dist/elements/a-toast.d.ts +10 -45
- package/dist/elements/a-toast.js +80 -66
- package/dist/elements/a-toaster.css +1 -1
- package/dist/elements/a-toaster.js +9 -44
- package/dist/elements/a-tooltip.css +1 -1
- package/dist/elements/a-tooltip.d.ts +1 -1
- package/dist/elements/a-tooltip.js +142 -136
- package/dist/elements/copy-behavior.d.ts +1 -1
- package/dist/elements/copy-behavior.js +21 -21
- package/dist/elements/index.d.ts +3 -3
- package/dist/elements/index.js +3 -7
- package/dist/elements/input-focus-modality.d.ts +15 -0
- package/dist/elements/input-focus-modality.js +44 -0
- package/dist/elements/input-trailing-actions.d.ts +5 -0
- package/dist/elements/input-trailing-actions.js +38 -0
- package/dist/elements/shadow-aria.d.ts +2 -0
- package/dist/elements/shadow-aria.js +2 -1
- package/dist/elements/value-input.d.ts +3 -0
- package/dist/elements/value-input.js +12 -0
- package/dist/general_types.d.ts +103 -96
- package/dist/index.d.ts +1 -1
- package/dist/input-events.d.ts +4 -0
- package/dist/input-events.js +15 -0
- package/dist/jsx-runtime.d.ts +70 -23
- package/dist/jsx-runtime.js +26 -19
- package/dist/native-event-props.d.ts +2 -0
- package/dist/native-event-props.js +10 -0
- package/dist/reset.css +1 -1
- package/dist/theme-antithesis.css +10 -1
- package/dist/theme-antune.css +1 -1
- package/docs/accessibility.md +17 -3
- package/docs/changelog.md +348 -2
- package/docs/comparison.md +2 -2
- package/docs/components/avatar.md +5 -0
- package/docs/components/banner.md +117 -187
- package/docs/components/button.md +22 -0
- package/docs/components/card.md +74 -28
- package/docs/components/checkbox.md +9 -10
- package/docs/components/dialog.md +83 -32
- package/docs/components/expander.md +198 -435
- package/docs/components/icon.md +11 -17
- package/docs/components/input-autocomplete.md +152 -52
- package/docs/components/input-date.md +175 -148
- package/docs/components/input-time.md +81 -38
- package/docs/components/input.md +343 -349
- package/docs/components/loader.md +2 -1
- package/docs/components/menu.md +35 -6
- package/docs/components/panel.md +18 -0
- package/docs/components/progress.md +83 -49
- package/docs/components/radio.md +39 -43
- package/docs/components/select-faceted.md +54 -7
- package/docs/components/select.md +390 -386
- package/docs/components/slider.md +136 -19
- package/docs/components/steps.md +2 -1
- package/docs/components/switch.md +8 -9
- package/docs/components/tabs.md +110 -104
- package/docs/components/text.md +110 -86
- package/docs/components/title.md +47 -33
- package/docs/components/toaster.md +242 -84
- package/docs/components/tooltip.md +204 -113
- package/docs/install-config.md +183 -26
- package/docs/packages/plot.md +170 -148
- package/docs/theming.md +7 -0
- package/package.json +41 -3
- package/theme-antithesis-license.md +66 -0
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { BaseProps } from "../general_types";
|
|
2
2
|
export interface TooltipProps extends BaseProps {
|
|
3
|
-
/**
|
|
4
|
-
* Lives in the light DOM, so it's styleable with your own plain CSS. */
|
|
3
|
+
/** Supplementary text or markup. Content stays in light DOM for application CSS. */
|
|
5
4
|
children?: React.ReactNode;
|
|
6
|
-
/**
|
|
7
|
-
* ~`50` for a near-instant tooltip (0 has caused issues in practice).
|
|
5
|
+
/** Wait in milliseconds after hover or keyboard focus. Use `50` for a short delay.
|
|
8
6
|
* @defaultValue 300 */
|
|
9
7
|
delay?: number;
|
|
10
8
|
/** Which side of the anchor the bubble prefers. Auto-flips to the other
|
|
@@ -18,10 +16,9 @@ export interface TooltipProps extends BaseProps {
|
|
|
18
16
|
* pinned (anchored beneath the target) by default; pass `follow` for the
|
|
19
17
|
* cursor-tracking behavior, which fades by distance as the cursor leaves. */
|
|
20
18
|
follow?: boolean;
|
|
21
|
-
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* can't follow the cursor, even with `follow`). */
|
|
19
|
+
/** Keep content available while the pointer or keyboard focus is inside it.
|
|
20
|
+
* Enables pointer events and pins the bubble even with `follow`. Essential
|
|
21
|
+
* actions belong in a Menu or Dialog with an explicit trigger. */
|
|
25
22
|
interactive?: boolean;
|
|
26
23
|
/** Only show when the target is actually truncated (its text overflows and is
|
|
27
24
|
* ellipsized); a label that fits gets no tooltip. The check is a UI-thread
|
|
@@ -49,13 +46,12 @@ export interface TooltipProps extends BaseProps {
|
|
|
49
46
|
*
|
|
50
47
|
* @example Basic usage
|
|
51
48
|
* ```tsx
|
|
52
|
-
* import { Tooltip } from '@antadesign/anta'
|
|
49
|
+
* import { Tooltip, Button } from '@antadesign/anta'
|
|
53
50
|
* import '@antadesign/anta/elements'
|
|
54
51
|
*
|
|
55
|
-
* <
|
|
56
|
-
* Save
|
|
52
|
+
* <Button label="Save">
|
|
57
53
|
* <Tooltip>Saves your work</Tooltip>
|
|
58
|
-
* </
|
|
54
|
+
* </Button>
|
|
59
55
|
* ```
|
|
60
56
|
*
|
|
61
57
|
* @example Above the anchor, rich content
|
|
@@ -70,10 +66,9 @@ export interface TooltipProps extends BaseProps {
|
|
|
70
66
|
*
|
|
71
67
|
* @example Follow the cursor
|
|
72
68
|
* ```tsx
|
|
73
|
-
* <
|
|
74
|
-
* Hover me
|
|
69
|
+
* <Button label="Hover me">
|
|
75
70
|
* <Tooltip follow>Tracks the pointer</Tooltip>
|
|
76
|
-
* </
|
|
71
|
+
* </Button>
|
|
77
72
|
* ```
|
|
78
73
|
*/
|
|
79
74
|
export declare const Tooltip: ({ delay, placement, round, follow, interactive, truncatedOnly, truncatedSelector, className, style, children, ...rest }: TooltipProps) => any;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The copy target for a copy preset (`ButtonCopy` / `MenuItemCopy`) — exactly
|
|
3
3
|
* one of a literal string, a DOM region, or the page URL. The write itself is
|
|
4
4
|
* performed by the slotted `<a-copy>` element; these props map to its attributes
|
|
5
|
-
* via `
|
|
5
|
+
* via `useCopyElementProps`. `copyWithUrl` / `onCopyRequest` are only meaningful for
|
|
6
6
|
* the string target, so the union pins them `never` elsewhere.
|
|
7
7
|
*/
|
|
8
8
|
export type CopyTarget = {
|
|
@@ -40,7 +40,7 @@ export type CopyTarget = {
|
|
|
40
40
|
copyWithUrl?: never;
|
|
41
41
|
onCopyRequest?: never;
|
|
42
42
|
};
|
|
43
|
-
/** Everything `
|
|
43
|
+
/** Everything `useCopyElementProps` reads: the target plus the resolved `onCopied`
|
|
44
44
|
* (the preset passes its feedback-wrapped handler) and the `toast` opt-in. */
|
|
45
45
|
type CopyElementInput = {
|
|
46
46
|
copy?: string;
|
|
@@ -63,7 +63,18 @@ export declare function copyElementProps(p: CopyElementInput): {
|
|
|
63
63
|
readonly toast: "" | undefined;
|
|
64
64
|
readonly 'copied-label': string | undefined;
|
|
65
65
|
readonly oncopydone: ((e: any) => void) | undefined;
|
|
66
|
-
readonly oncopyrequest: (() => void) | undefined;
|
|
66
|
+
readonly oncopyrequest: ((e: any) => void) | undefined;
|
|
67
|
+
};
|
|
68
|
+
/** @internal Apply the shared browser hydration option to copy event props. */
|
|
69
|
+
export declare function useCopyElementProps(p: CopyElementInput): {
|
|
70
|
+
copy: string | undefined;
|
|
71
|
+
'copy-node': string | undefined;
|
|
72
|
+
'copy-url': "" | undefined;
|
|
73
|
+
'copy-with-url': "" | undefined;
|
|
74
|
+
toast: "" | undefined;
|
|
75
|
+
'copied-label': string | undefined;
|
|
76
|
+
oncopydone?: ((e: any) => void) | undefined;
|
|
77
|
+
oncopyrequest?: ((e: any) => void) | undefined;
|
|
67
78
|
};
|
|
68
79
|
/** True when these props copy a DOM node — the host control must then be marked
|
|
69
80
|
* `data-copy-node-button` so the serializer strips it from the copied region. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { nativeStateChange } from "../anta_helpers";
|
|
2
|
+
import { useNativeEventProps } from "../native-event-props";
|
|
2
3
|
function copyElementProps(p) {
|
|
3
4
|
const { copy, copyNode, copyUrl, copyWithUrl, onCopyRequest, onCopied, toast, copiedLabel } = p;
|
|
4
5
|
return {
|
|
@@ -8,14 +9,24 @@ function copyElementProps(p) {
|
|
|
8
9
|
"copy-with-url": copyWithUrl ? "" : void 0,
|
|
9
10
|
toast: toast ? "" : void 0,
|
|
10
11
|
"copied-label": copiedLabel,
|
|
11
|
-
oncopydone: onCopied ? (e) =>
|
|
12
|
-
|
|
12
|
+
oncopydone: onCopied ? (e) => {
|
|
13
|
+
const result = nativeStateChange(e);
|
|
14
|
+
if (result.isOwn) onCopied(result.detail?.ok ?? false);
|
|
15
|
+
} : void 0,
|
|
16
|
+
oncopyrequest: onCopyRequest ? (e) => {
|
|
17
|
+
if (nativeStateChange(e).isOwn) onCopyRequest();
|
|
18
|
+
} : void 0
|
|
13
19
|
};
|
|
14
20
|
}
|
|
21
|
+
function useCopyElementProps(p) {
|
|
22
|
+
const { oncopydone, oncopyrequest, ...attributes } = copyElementProps(p);
|
|
23
|
+
return { ...attributes, ...useNativeEventProps({ oncopydone, oncopyrequest }) };
|
|
24
|
+
}
|
|
15
25
|
function isNodeCopy(p) {
|
|
16
26
|
return p.copyNode != null && p.copyNode !== false;
|
|
17
27
|
}
|
|
18
28
|
export {
|
|
19
29
|
copyElementProps,
|
|
20
|
-
isNodeCopy
|
|
30
|
+
isNodeCopy,
|
|
31
|
+
useCopyElementProps
|
|
21
32
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { OptionValue, SelectGroup, SelectItem, SelectOption, SelectSubmenu } from './Select';
|
|
2
|
+
interface Leaf<V extends OptionValue> {
|
|
3
|
+
kind: 'option';
|
|
4
|
+
opt: SelectOption<V>;
|
|
5
|
+
disabled: boolean;
|
|
6
|
+
group?: string;
|
|
7
|
+
}
|
|
8
|
+
export type SelectNode<V extends OptionValue> = Leaf<V> | ({
|
|
9
|
+
key: string;
|
|
10
|
+
disabled: boolean;
|
|
11
|
+
children: SelectNode<V>[];
|
|
12
|
+
} & ({
|
|
13
|
+
kind: 'group';
|
|
14
|
+
source: SelectGroup<V>;
|
|
15
|
+
} | {
|
|
16
|
+
kind: 'submenu';
|
|
17
|
+
source: SelectSubmenu<V>;
|
|
18
|
+
}));
|
|
19
|
+
export declare function prepareSelectOptions<V extends OptionValue>(items: SelectItem<V>[], matches?: (option: SelectOption<V>) => boolean): {
|
|
20
|
+
tree: SelectNode<V>[];
|
|
21
|
+
allLeaves: Leaf<V>[];
|
|
22
|
+
visibleLeaves: Leaf<V>[];
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { normalizeOpt } from "./select-options";
|
|
2
|
+
function prepareSelectOptions(items, matches) {
|
|
3
|
+
const allLeaves = [];
|
|
4
|
+
const visibleLeaves = [];
|
|
5
|
+
const walk = (items2, group, disabled = false) => {
|
|
6
|
+
const nodes = [];
|
|
7
|
+
items2.forEach((raw, index) => {
|
|
8
|
+
if (typeof raw !== "string" && Array.isArray(raw.submenu)) {
|
|
9
|
+
const source = raw;
|
|
10
|
+
const effectiveDisabled = disabled || !!source.disabled;
|
|
11
|
+
const children = walk(source.submenu, source.label, effectiveDisabled);
|
|
12
|
+
if (children.length) nodes.push({ kind: "submenu", source, disabled: effectiveDisabled, children, key: `sub-${index}-${source.label}` });
|
|
13
|
+
} else if (typeof raw !== "string" && Array.isArray(raw.options)) {
|
|
14
|
+
const source = raw;
|
|
15
|
+
const effectiveDisabled = disabled || !!source.disabled;
|
|
16
|
+
const children = walk(source.options, source.label, effectiveDisabled);
|
|
17
|
+
if (children.length) nodes.push({ kind: "group", source, disabled: effectiveDisabled, children, key: `grp-${index}-${source.label}` });
|
|
18
|
+
} else {
|
|
19
|
+
const opt = normalizeOpt(raw);
|
|
20
|
+
const leaf = { kind: "option", opt, disabled: disabled || !!opt.disabled, group };
|
|
21
|
+
allLeaves.push(leaf);
|
|
22
|
+
if (!matches || matches(opt)) {
|
|
23
|
+
visibleLeaves.push(leaf);
|
|
24
|
+
nodes.push(leaf);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
return nodes;
|
|
29
|
+
};
|
|
30
|
+
const tree = walk(items);
|
|
31
|
+
return { tree, allLeaves, visibleLeaves };
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
prepareSelectOptions
|
|
35
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Use a harmless base when importing element classes without a browser DOM. */
|
|
2
|
+
declare const NativeHTMLElement: typeof HTMLElement;
|
|
3
|
+
/** Base for custom elements that can live in a different document or iframe. */
|
|
4
|
+
export declare class HTMLElementBase extends NativeHTMLElement {
|
|
5
|
+
/** This element's own window, including when rendered in an iframe. */
|
|
6
|
+
protected get view(): Window & typeof globalThis;
|
|
7
|
+
/** This element's own document. */
|
|
8
|
+
protected get doc(): Document;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const NativeHTMLElement = typeof HTMLElement !== "undefined" ? HTMLElement : class {
|
|
2
|
+
};
|
|
3
|
+
class HTMLElementBase extends NativeHTMLElement {
|
|
4
|
+
/** This element's own window, including when rendered in an iframe. */
|
|
5
|
+
get view() {
|
|
6
|
+
return this.ownerDocument?.defaultView ?? window;
|
|
7
|
+
}
|
|
8
|
+
/** This element's own document. */
|
|
9
|
+
get doc() {
|
|
10
|
+
return this.ownerDocument ?? document;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
HTMLElementBase
|
|
15
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-banner{--banner-bg: var(--bg-4);--banner-border: var(--border-4);--banner-text: var(--text-2);display:flex;align-items:center;justify-content:flex-start;flex-wrap:wrap;gap:4px 1ch;position:relative;box-sizing:border-box;width:100%;min-height:40px;padding-block:6px;padding-inline:16px 48px;color:var(--banner-text);background:var(--banner-bg);border:0 solid var(--banner-border);border-radius:0;overflow:clip;overflow-clip-margin:3px;interpolate-size:allow-keywords;transition:opacity .16s ease,block-size .2s ease,padding-block .2s ease,border-block-width .2s ease,display .2s allow-discrete}a-banner[align=center]{justify-content:center;padding-inline:48px}a-banner[round]{border-radius:var(--banner-round, 999px);@supports (border-radius: attr(probe type(<length>),1px)){--banner-round: attr(round type(<length>))}}a-banner
|
|
1
|
+
@layer base,anta,components,utilities;@layer anta.reset,anta.components,anta.theme;@layer anta.components{a-banner{--banner-bg: var(--bg-4);--banner-border: var(--border-4);--banner-text: var(--text-2);--banner-round: initial;--banner-tone-source: initial;display:flex;align-items:center;justify-content:flex-start;flex-wrap:wrap;gap:4px 1ch;position:relative;box-sizing:border-box;width:100%;min-height:40px;padding-block:6px;padding-inline:16px 48px;color:var(--banner-text);background:var(--banner-bg);border:0 solid var(--banner-border);border-radius:0;overflow:clip;overflow-clip-margin:3px;interpolate-size:allow-keywords;transition:opacity .16s ease,block-size .2s ease,padding-block .2s ease,border-block-width .2s ease,display .2s allow-discrete}a-banner[align=center]{justify-content:center;padding-inline:48px}a-banner[round]{border-radius:var(--banner-round, 999px);@supports (border-radius: attr(probe type(<length>),1px)){--banner-round: attr(round type(<length>))}}a-banner>a-banner-content{display:contents}a-banner>a-banner-actions{display:flex;align-items:center;gap:4px;flex-shrink:0}a-banner>a-banner-actions:empty{display:none}a-banner>a-banner-message:empty,a-banner>:is(a-banner-message,a-banner-content,a-banner-actions,a-banner-close)[hidden]{display:none}a-banner>a-banner-close{position:absolute;inset-inline-end:0;inset-block:0;display:grid;place-items:center;opacity:.65;transition:opacity .15s ease}a-banner>a-banner-close:hover,a-banner>a-banner-close:focus-within{opacity:1}a-banner>a-banner-close>a-button{height:100%;width:40px}a-banner-message{font-size:14px;line-height:20px;font-weight:475;text-align:start}a-banner[align=center]>a-banner-message{text-align:center}a-banner[tone=brand]{--banner-bg: var(--bg-4-brand);--banner-border: var(--border-4-brand);--banner-text: var(--text-2-brand)}a-banner[tone=info]{--banner-bg: var(--bg-4-info);--banner-border: var(--border-4-info);--banner-text: var(--text-2-info)}a-banner[tone=success]{--banner-bg: var(--bg-4-success);--banner-border: var(--border-4-success);--banner-text: var(--text-2-success)}a-banner[tone=warning]{--banner-bg: var(--bg-4-warning);--banner-border: var(--border-4-warning);--banner-text: var(--text-2-warning)}a-banner[tone=critical]{--banner-bg: var(--bg-4-critical);--banner-border: var(--border-4-critical);--banner-text: var(--text-2-critical)}a-banner[tone]:not([tone=""],[tone=neutral],[tone=brand],[tone=info],[tone=success],[tone=warning],[tone=critical]){--banner-tone-source: currentColor;--banner-text: light-dark( oklch(from var(--banner-tone-source) .5 .125 h), oklch(from var(--banner-tone-source) .77 .11 h) );--banner-bg: light-dark( oklch(from var(--banner-tone-source) .955 .02 h), oklch(from var(--banner-tone-source) .185 .05 h) );--banner-border: light-dark( oklch(from var(--banner-tone-source) .9 .04 h), oklch(from var(--banner-tone-source) .26 .06 h) );@supports (color: attr(probe type(<color>),red)){--banner-tone-source: attr(tone type(<color>), currentColor)}}a-banner[state]:not([state=open]),a-banner:not([state])[default-state=closed]:not(:state(open)),a-banner:not([state]):state(closed){display:none;block-size:0;min-block-size:0;padding-block:0;border-block-width:0;opacity:0}@media(forced-colors:active){a-banner{border-width:1px;border-color:CanvasText}}@media(prefers-reduced-motion:reduce){a-banner,a-banner>a-banner-close{transition:none}}}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { HTMLElementBase } from '../anta_helpers';
|
|
2
2
|
import './a-banner.css';
|
|
3
|
+
/** Light-DOM notice with declarative regions and external styling. The element
|
|
4
|
+
* owns dismissal through ElementInternals, without changing
|
|
5
|
+
* application-owned markup, attributes, styles, or ARIA. */
|
|
3
6
|
export declare class ABannerElement extends HTMLElementBase {
|
|
4
7
|
#private;
|
|
5
8
|
static observedAttributes: string[];
|
|
6
9
|
constructor();
|
|
7
10
|
connectedCallback(): void;
|
|
8
|
-
attributeChangedCallback(name: string): void;
|
|
11
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
|
9
12
|
}
|
|
10
13
|
export declare function register_a_banner(): void;
|
|
@@ -1,145 +1,55 @@
|
|
|
1
1
|
import { HTMLElementBase, installDismissTrigger, parseOpenState } from "../anta_helpers";
|
|
2
2
|
import "./a-banner.css";
|
|
3
|
-
const DISMISS_TRIGGER = "dismissrequest";
|
|
4
|
-
const DISMISS_ATTR = "data-banner-dismiss";
|
|
5
|
-
const SHADOW_STYLE = `
|
|
6
|
-
slot[name="message"], slot:not([name]) { display: contents; }
|
|
7
|
-
|
|
8
|
-
slot[name="actions"] {
|
|
9
|
-
display: flex;
|
|
10
|
-
align-items: center;
|
|
11
|
-
gap: 4px;
|
|
12
|
-
flex-shrink: 0;
|
|
13
|
-
}
|
|
14
|
-
slot[name="actions"][hidden] { display: none; }
|
|
15
|
-
|
|
16
|
-
slot[name="close"] {
|
|
17
|
-
position: absolute;
|
|
18
|
-
inset-inline-end: 0;
|
|
19
|
-
inset-block: 0;
|
|
20
|
-
display: grid;
|
|
21
|
-
place-items: center;
|
|
22
|
-
opacity: 0.65;
|
|
23
|
-
transition: opacity 150ms ease;
|
|
24
|
-
}
|
|
25
|
-
slot[name="close"]:hover,
|
|
26
|
-
slot[name="close"]:focus-within {
|
|
27
|
-
opacity: 1;
|
|
28
|
-
}
|
|
29
|
-
`;
|
|
30
|
-
const parseState = parseOpenState;
|
|
31
3
|
class ABannerElement extends HTMLElementBase {
|
|
32
4
|
static observedAttributes = ["state"];
|
|
33
|
-
// Visibility is held here as a custom state (`:state(open)` / `:state(closed)`),
|
|
34
|
-
// NOT a host attribute — declarative-DOM safe (no host mutation, no reconcile
|
|
35
|
-
// churn). This is the ONLY declarative-safe self-hide channel, so a runtime
|
|
36
|
-
// (uncontrolled) ✕ dismiss needs CustomStateSet + the CSS `:state()` selector
|
|
37
|
-
// (Chrome 90+, Safari 17.4+, Firefox 126+); below that the ✕ can't self-hide (an
|
|
38
|
-
// attribute fallback would violate the no-host-mutation rule). Controlled mode
|
|
39
|
-
// degrades everywhere — the `state="closed"` attribute the wrapper sets has the
|
|
40
|
-
// `[state="closed"]` CSS fallback, which needs no custom-state support.
|
|
41
5
|
#internals;
|
|
42
|
-
// `default-state` seeds the uncontrolled intent ONCE, on the first connect; a
|
|
43
|
-
// re-parent (disconnect → reconnect) then keeps the applied state (which lives
|
|
44
|
-
// off-DOM in #internals and survives the move) instead of re-seeding `open` over a
|
|
45
|
-
// banner the user already dismissed. Mirrors a-dialog's #seeded.
|
|
46
6
|
#seeded = false;
|
|
47
7
|
constructor() {
|
|
48
8
|
super();
|
|
49
|
-
this.#internals =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
messageSlot.name = "message";
|
|
55
|
-
messageSlot.setAttribute("part", "message");
|
|
56
|
-
const contentSlot = document.createElement("slot");
|
|
57
|
-
contentSlot.setAttribute("part", "content");
|
|
58
|
-
const actionsSlot = document.createElement("slot");
|
|
59
|
-
actionsSlot.name = "actions";
|
|
60
|
-
actionsSlot.setAttribute("part", "actions");
|
|
61
|
-
const syncActionsSlot = () => {
|
|
62
|
-
actionsSlot.hidden = !actionsSlot.assignedNodes({ flatten: true }).some((node) => {
|
|
63
|
-
if (node.nodeType === Node.TEXT_NODE) return node.textContent?.trim() !== "";
|
|
64
|
-
if (node.nodeType !== Node.ELEMENT_NODE) return false;
|
|
65
|
-
const element = node;
|
|
66
|
-
return !element.hasAttribute("data-anta-banner-actions-wrapper") || !element.matches(":empty");
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
actionsSlot.hidden = true;
|
|
70
|
-
actionsSlot.addEventListener("slotchange", syncActionsSlot);
|
|
71
|
-
const closeSlot = document.createElement("slot");
|
|
72
|
-
closeSlot.name = "close";
|
|
73
|
-
closeSlot.setAttribute("part", "close");
|
|
74
|
-
shadow.append(style, messageSlot, contentSlot, actionsSlot, closeSlot);
|
|
75
|
-
syncActionsSlot();
|
|
76
|
-
this.addEventListener(DISMISS_TRIGGER, (e) => {
|
|
77
|
-
e.stopPropagation();
|
|
9
|
+
this.#internals = this.attachInternals();
|
|
10
|
+
this.addEventListener("dismissrequest", (event) => {
|
|
11
|
+
const banner = event.composedPath().find((node) => node.nodeType === 1 && node.localName === "a-banner");
|
|
12
|
+
if (banner !== this) return;
|
|
13
|
+
event.stopPropagation();
|
|
78
14
|
this.#requestDismiss();
|
|
79
15
|
});
|
|
80
|
-
installDismissTrigger(this,
|
|
16
|
+
installDismissTrigger(this, "data-banner-dismiss", () => this.#requestDismiss());
|
|
81
17
|
}
|
|
82
|
-
/** Controlled mode: the `state` attribute is present and owns visibility. */
|
|
83
18
|
get #controlled() {
|
|
84
19
|
return this.hasAttribute("state");
|
|
85
20
|
}
|
|
86
|
-
/** The currently *applied* state (read from the custom state — the source of
|
|
87
|
-
* truth for what's painted). Reads open until the element has applied a state.
|
|
88
|
-
* Both `?.` guard engines with ElementInternals but no CustomStateSet (`.states`
|
|
89
|
-
* undefined), where reading it would otherwise throw inside the ✕ click. */
|
|
90
21
|
get #current() {
|
|
91
|
-
return this.#internals
|
|
22
|
+
return this.#internals.states.has("closed") ? "closed" : "open";
|
|
92
23
|
}
|
|
93
24
|
connectedCallback() {
|
|
94
25
|
if (this.#controlled) {
|
|
95
|
-
this.#applyState(
|
|
26
|
+
this.#applyState(parseOpenState(this.getAttribute("state")));
|
|
96
27
|
} else if (!this.#seeded) {
|
|
97
|
-
this.#applyState(this
|
|
98
|
-
this.#seeded = true;
|
|
28
|
+
this.#applyState(this.getAttribute("default-state") === "closed" ? "closed" : "open");
|
|
99
29
|
}
|
|
30
|
+
this.#seeded = true;
|
|
100
31
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
* `parseState` here. A hand-authored `<a-banner>` with no attributes shows.) */
|
|
105
|
-
#seedState() {
|
|
106
|
-
return this.getAttribute("default-state") === "closed" ? "closed" : "open";
|
|
32
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
33
|
+
if (oldValue === newValue) return;
|
|
34
|
+
if (name === "state" && this.#controlled) this.#applyState(parseOpenState(newValue));
|
|
107
35
|
}
|
|
108
|
-
attributeChangedCallback(name) {
|
|
109
|
-
if (name === "state" && this.#controlled) this.#applyState(parseState(this.getAttribute("state")));
|
|
110
|
-
}
|
|
111
|
-
/** Mirror the state to `:state(open)` / `:state(closed)` (idempotent). The
|
|
112
|
-
* external sheet collapses the host on `:state(closed)`. Off-DOM only. */
|
|
113
36
|
#applyState(state) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (state === "closed") {
|
|
117
|
-
this.#internals?.states?.add("closed");
|
|
118
|
-
this.#internals?.states?.delete("open");
|
|
119
|
-
} else {
|
|
120
|
-
this.#internals?.states?.add("open");
|
|
121
|
-
this.#internals?.states?.delete("closed");
|
|
122
|
-
}
|
|
123
|
-
} catch {
|
|
124
|
-
}
|
|
37
|
+
this.#internals.states.delete(state === "closed" ? "open" : "closed");
|
|
38
|
+
this.#internals.states.add(state);
|
|
125
39
|
}
|
|
126
|
-
/** Announce a requested dismiss (cancelable, before applying), then — uncontrolled
|
|
127
|
-
* and un-vetoed — apply it. Controlled: never self-apply; the consumer answers
|
|
128
|
-
* via `state`. See STATEFUL-COMPONENTS.md. */
|
|
129
40
|
#requestDismiss() {
|
|
130
41
|
if (this.#current === "closed") return;
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
42
|
+
const controlled = this.#controlled;
|
|
43
|
+
const accepted = this.dispatchEvent(new this.view.CustomEvent("statechange", {
|
|
44
|
+
cancelable: true,
|
|
45
|
+
detail: { next: "closed", prev: "open" }
|
|
46
|
+
}));
|
|
47
|
+
if (!controlled && !this.#controlled && accepted) this.#applyState("closed");
|
|
136
48
|
}
|
|
137
49
|
}
|
|
138
50
|
function register_a_banner() {
|
|
139
51
|
if (typeof customElements === "undefined") return;
|
|
140
|
-
if (!customElements.get("a-banner"))
|
|
141
|
-
customElements.define("a-banner", ABannerElement);
|
|
142
|
-
}
|
|
52
|
+
if (!customElements.get("a-banner")) customElements.define("a-banner", ABannerElement);
|
|
143
53
|
}
|
|
144
54
|
register_a_banner();
|
|
145
55
|
export {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HTMLElementBase, SYNC_POPUP_ARIA, type PopupAriaRelations } from "../anta_helpers";
|
|
1
|
+
import { HTMLElementBase, SYNC_POPUP_ARIA, type PopupAriaRelations, SYNC_TEXT_TOGGLE, type TextToggleAria } from "../anta_helpers";
|
|
2
2
|
import "./a-button.css";
|
|
3
3
|
declare global {
|
|
4
4
|
interface Document {
|
|
@@ -73,6 +73,7 @@ export declare class AButtonElement extends HTMLElementBase {
|
|
|
73
73
|
connectedCallback(): void;
|
|
74
74
|
disconnectedCallback(): void;
|
|
75
75
|
attributeChangedCallback(): void;
|
|
76
|
+
[SYNC_TEXT_TOGGLE](state: TextToggleAria): void;
|
|
76
77
|
[SYNC_POPUP_ARIA](relations: PopupAriaRelations): void;
|
|
77
78
|
}
|
|
78
79
|
export declare function register_a_button(): void;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HTMLElementBase, SYNC_POPUP_ARIA } from "../anta_helpers";
|
|
1
|
+
import { HTMLElementBase, SYNC_POPUP_ARIA, SYNC_TEXT_TOGGLE } from "../anta_helpers";
|
|
2
2
|
import { installKeyActivation } from "./key-activation";
|
|
3
3
|
import "./a-button.css";
|
|
4
4
|
function installDocumentHandlers(doc) {
|
|
@@ -18,6 +18,7 @@ class AButtonElement extends HTMLElementBase {
|
|
|
18
18
|
popupAriaSource;
|
|
19
19
|
#fieldObserver;
|
|
20
20
|
#field;
|
|
21
|
+
#textToggleSource;
|
|
21
22
|
constructor() {
|
|
22
23
|
super();
|
|
23
24
|
try {
|
|
@@ -27,6 +28,8 @@ class AButtonElement extends HTMLElementBase {
|
|
|
27
28
|
}
|
|
28
29
|
connectedCallback() {
|
|
29
30
|
installDocumentHandlers(this.doc);
|
|
31
|
+
if (this.parentElement?.localName === "a-text")
|
|
32
|
+
this.dispatchEvent(new Event("anta-text-control-ready", { bubbles: true }));
|
|
30
33
|
if (this.parentElement?.localName === "a-select-field") {
|
|
31
34
|
this.#field = this.parentElement;
|
|
32
35
|
this.#fieldObserver = new MutationObserver(() => this.#syncField());
|
|
@@ -36,6 +39,7 @@ class AButtonElement extends HTMLElementBase {
|
|
|
36
39
|
}
|
|
37
40
|
}
|
|
38
41
|
disconnectedCallback() {
|
|
42
|
+
if (this.#textToggleSource) this[SYNC_TEXT_TOGGLE]({ source: this.#textToggleSource, clear: true });
|
|
39
43
|
if (!this.#field) return;
|
|
40
44
|
this.#fieldObserver?.disconnect();
|
|
41
45
|
this.#field?.removeEventListener("click", this.#onFieldClick);
|
|
@@ -61,6 +65,19 @@ class AButtonElement extends HTMLElementBase {
|
|
|
61
65
|
if (this.hasAttribute("disabled") || this.hasAttribute("loading")) return;
|
|
62
66
|
if (event.composedPath().some((node) => node instanceof Element && node.localName === "a-select-label")) this.focus();
|
|
63
67
|
};
|
|
68
|
+
[SYNC_TEXT_TOGGLE](state) {
|
|
69
|
+
if (!this.internals) return;
|
|
70
|
+
if (state.clear) {
|
|
71
|
+
if (this.#textToggleSource !== state.source) return;
|
|
72
|
+
this.#textToggleSource = void 0;
|
|
73
|
+
this.internals.ariaExpanded = null;
|
|
74
|
+
this.internals.ariaLabel = null;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
this.#textToggleSource = state.source;
|
|
78
|
+
this.internals.ariaExpanded = state.expanded ? "true" : "false";
|
|
79
|
+
this.internals.ariaLabel = state.expanded ? "Show less" : "Show more";
|
|
80
|
+
}
|
|
64
81
|
[SYNC_POPUP_ARIA](relations) {
|
|
65
82
|
if (!this.internals || !("ariaControlsElements" in this.internals)) return;
|
|
66
83
|
if (relations.clear) {
|
|
@@ -21,18 +21,18 @@ import './a-calendar.css';
|
|
|
21
21
|
* `{ next, prev, reason }`: ISO-string dates (or `null`), `reason` ∈
|
|
22
22
|
* `'user' | 'reset' | 'restore'`. `preventDefault()` vetoes a `'user'` pick in
|
|
23
23
|
* uncontrolled mode.
|
|
24
|
-
* - `change` — fired AFTER a selection applies
|
|
25
|
-
* reset/restore.
|
|
24
|
+
* - `change` — fired AFTER a selection applies, including controlled attribute
|
|
25
|
+
* updates and accepted reset/restore.
|
|
26
26
|
* - `navigate` — `detail: { date }` (ISO). Fired on keyboard navigation (and
|
|
27
27
|
* when the target month isn't rendered) so the renderer can move the roving tab
|
|
28
28
|
* stop and flip the displayed month.
|
|
29
29
|
*
|
|
30
30
|
* ## Controlled vs uncontrolled (like `<a-radio-group>`)
|
|
31
31
|
*
|
|
32
|
-
* Presence of
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
32
|
+
* Presence of **`value`** = controlled: a pick requests a change through
|
|
33
|
+
* `statechange`; the renderer answers by updating `value`. With **`defaultvalue`**
|
|
34
|
+
* instead, the element owns selection and applies picks unless vetoed. Consumer
|
|
35
|
+
* property assignments reflect these inputs; picks never rewrite them.
|
|
36
36
|
*
|
|
37
37
|
* ## Selection & keyboard
|
|
38
38
|
*
|
|
@@ -47,8 +47,9 @@ export declare class ACalendarElement extends HTMLElementBase {
|
|
|
47
47
|
static formAssociated: boolean;
|
|
48
48
|
static observedAttributes: string[];
|
|
49
49
|
private internals?;
|
|
50
|
-
/**
|
|
50
|
+
/** Latest applied selection, retained when controlled state is removed. */
|
|
51
51
|
private selectedIso;
|
|
52
|
+
private seeded;
|
|
52
53
|
constructor();
|
|
53
54
|
connectedCallback(): void;
|
|
54
55
|
attributeChangedCallback(name: string, _old: string | null, value: string | null): void;
|
|
@@ -64,12 +65,12 @@ export declare class ACalendarElement extends HTMLElementBase {
|
|
|
64
65
|
* microtask so a just-rendered new month has committed. Signal: `"<iso>#<nonce>"`. */
|
|
65
66
|
private focusCell;
|
|
66
67
|
private emitState;
|
|
67
|
-
/**
|
|
68
|
-
get value(): string;
|
|
69
|
-
set value(
|
|
70
|
-
/**
|
|
71
|
-
get
|
|
72
|
-
set
|
|
68
|
+
/** Applied ISO date, or `null` when empty. String assignments supply controlled input. */
|
|
69
|
+
get value(): string | null;
|
|
70
|
+
set value(value: string | null | undefined);
|
|
71
|
+
/** Authored initial/reset date, or `null` when no default is supplied. */
|
|
72
|
+
get defaultValue(): string | null;
|
|
73
|
+
set defaultValue(value: string | null | undefined);
|
|
73
74
|
formResetCallback(): void;
|
|
74
75
|
formStateRestoreCallback(state: string): void;
|
|
75
76
|
}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { HTMLElementBase, isModifiedNavigationKey } from "../anta_helpers";
|
|
2
2
|
import { Temporal } from "temporal-polyfill";
|
|
3
3
|
import "./a-calendar.css";
|
|
4
|
+
import { upgradeValueProperties } from "./value-input";
|
|
4
5
|
class ACalendarElement extends HTMLElementBase {
|
|
5
6
|
static formAssociated = true;
|
|
6
7
|
static observedAttributes = ["value", "data-focus"];
|
|
7
8
|
internals;
|
|
8
|
-
/**
|
|
9
|
+
/** Latest applied selection, retained when controlled state is removed. */
|
|
9
10
|
selectedIso = null;
|
|
11
|
+
seeded = false;
|
|
10
12
|
constructor() {
|
|
11
13
|
super();
|
|
12
14
|
try {
|
|
@@ -16,27 +18,28 @@ class ACalendarElement extends HTMLElementBase {
|
|
|
16
18
|
}
|
|
17
19
|
this.addEventListener("click", this.onClick);
|
|
18
20
|
this.addEventListener("keydown", this.onKeydown);
|
|
21
|
+
upgradeValueProperties(this);
|
|
19
22
|
}
|
|
20
23
|
connectedCallback() {
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
this.value = v;
|
|
24
|
+
if (!this.seeded) {
|
|
25
|
+
this.selectedIso = this.#controlled ? this.currentIso() : this.getAttribute("defaultvalue") || null;
|
|
26
|
+
this.seeded = true;
|
|
25
27
|
}
|
|
26
|
-
this.selectedIso = this.getAttribute("value") || this.getAttribute("defaultvalue") || null;
|
|
27
28
|
this.applyFormValue(this.currentIso());
|
|
28
29
|
}
|
|
29
30
|
attributeChangedCallback(name, _old, value) {
|
|
30
31
|
if (name === "value") {
|
|
31
|
-
this.
|
|
32
|
+
const prev = this.selectedIso;
|
|
33
|
+
this.selectedIso = this.currentIso();
|
|
34
|
+
this.applyFormValue(this.selectedIso);
|
|
35
|
+
if (this.seeded && this.selectedIso !== prev) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
32
36
|
return;
|
|
33
37
|
}
|
|
34
38
|
if (name === "data-focus") {
|
|
35
39
|
this.focusCell(value);
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
|
-
/**
|
|
39
|
-
* in controlled mode); otherwise the element owns selection. */
|
|
42
|
+
/** A present value input keeps selection controlled, including an empty date. */
|
|
40
43
|
get #controlled() {
|
|
41
44
|
return this.hasAttribute("value");
|
|
42
45
|
}
|
|
@@ -145,37 +148,39 @@ class ACalendarElement extends HTMLElementBase {
|
|
|
145
148
|
}
|
|
146
149
|
// --- Public value API + form callbacks ----------------------------------
|
|
147
150
|
emitState(next, prev, reason) {
|
|
151
|
+
const controlled = this.#controlled;
|
|
152
|
+
if (!controlled) {
|
|
153
|
+
this.selectedIso = next;
|
|
154
|
+
this.applyFormValue(next);
|
|
155
|
+
}
|
|
148
156
|
this.dispatchEvent(
|
|
149
157
|
new CustomEvent("statechange", { bubbles: false, detail: { next, prev, reason } })
|
|
150
158
|
);
|
|
151
|
-
this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
159
|
+
if (!controlled) this.dispatchEvent(new Event("change", { bubbles: true }));
|
|
152
160
|
}
|
|
153
|
-
/**
|
|
161
|
+
/** Applied ISO date, or `null` when empty. String assignments supply controlled input. */
|
|
154
162
|
get value() {
|
|
155
|
-
return this.currentIso()
|
|
163
|
+
return this.currentIso();
|
|
156
164
|
}
|
|
157
|
-
set value(
|
|
158
|
-
|
|
159
|
-
this.
|
|
165
|
+
set value(value) {
|
|
166
|
+
if (value == null) this.removeAttribute("value");
|
|
167
|
+
else this.setAttribute("value", value);
|
|
160
168
|
}
|
|
161
|
-
/**
|
|
162
|
-
get
|
|
163
|
-
return this.getAttribute("
|
|
169
|
+
/** Authored initial/reset date, or `null` when no default is supplied. */
|
|
170
|
+
get defaultValue() {
|
|
171
|
+
return this.getAttribute("defaultvalue");
|
|
164
172
|
}
|
|
165
|
-
set
|
|
166
|
-
this.
|
|
173
|
+
set defaultValue(value) {
|
|
174
|
+
if (value == null) this.removeAttribute("defaultvalue");
|
|
175
|
+
else this.setAttribute("defaultvalue", value);
|
|
167
176
|
}
|
|
168
177
|
formResetCallback() {
|
|
169
178
|
const def = this.getAttribute("defaultvalue") || null;
|
|
170
179
|
const prev = this.currentIso();
|
|
171
|
-
this.selectedIso = def;
|
|
172
|
-
this.applyFormValue(def);
|
|
173
180
|
this.emitState(def, prev, "reset");
|
|
174
181
|
}
|
|
175
182
|
formStateRestoreCallback(state) {
|
|
176
183
|
const prev = this.currentIso();
|
|
177
|
-
this.selectedIso = state || null;
|
|
178
|
-
this.applyFormValue(state || null);
|
|
179
184
|
this.emitState(state || null, prev, "restore");
|
|
180
185
|
}
|
|
181
186
|
}
|