annotate design_system/src/components/forms.js @ 265:056790c4fb0d

add role-aware Epi assistant prompts Add verified June knowledge, guest/member/admin Copilot profiles, profile-isolated session recovery, animated Epi greetings, and a single authoritative runtime config workflow for inference. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 10:50:30 -0700
parents 2b6e732087ff
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
254
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1 let nextFormId = 1;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
2
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
3 function uniqueId(prefix) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
4 let id;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
5 do id = `${prefix}-${nextFormId++}`;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
6 while (document.getElementById(id));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
7 return id;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
8 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
9
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
10 function rememberAttribute(state, element, name) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
11 let attributes = state.get(element);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
12 if (!attributes) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
13 attributes = new Map();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
14 state.set(element, attributes);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
15 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
16 if (!attributes.has(name)) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
17 attributes.set(name, element.getAttribute(name));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
18 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
19 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
20
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
21 function setManagedAttribute(state, element, name, value) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
22 rememberAttribute(state, element, name);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
23 if (value === null) element.removeAttribute(name);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
24 else element.setAttribute(name, value);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
25 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
26
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
27 function restoreElement(state, element) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
28 const attributes = state.get(element);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
29 if (!attributes) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
30 for (const [name, value] of attributes) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
31 if (value === null) element.removeAttribute(name);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
32 else element.setAttribute(name, value);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
33 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
34 state.delete(element);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
35 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
36
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
37 function restoreAttribute(state, element, name) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
38 const attributes = state.get(element);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
39 if (!attributes?.has(name)) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
40 const value = attributes.get(name);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
41 if (value === null) element.removeAttribute(name);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
42 else element.setAttribute(name, value);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
43 attributes.delete(name);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
44 if (!attributes.size) state.delete(element);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
45 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
46
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
47 function restoreAttributes(state) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
48 for (const element of [...state.keys()]) restoreElement(state, element);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
49 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
50
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
51 function originalAttribute(state, element, name) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
52 const attributes = state.get(element);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
53 return attributes?.has(name)
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
54 ? attributes.get(name)
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
55 : element.getAttribute(name);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
56 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
57
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
58 function ensureId(state, element, prefix) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
59 const owner = element.id && document.getElementById(element.id);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
60 if (!element.id || (owner && owner !== element)) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
61 setManagedAttribute(state, element, "id", uniqueId(prefix));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
62 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
63 return element.id;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
64 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
65
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
66 function emit(element, type, detail) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
67 element.dispatchEvent(new CustomEvent(type, {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
68 bubbles: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
69 detail,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
70 }));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
71 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
72
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
73 class NativeControl extends HTMLElement {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
74 connectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
75 if (!this._observer) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
76 this._observer = new MutationObserver(() => this.sync());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
77 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
78 this._observer.observe(this, { childList: true, subtree: true });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
79 this.sync();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
80 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
81
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
82 disconnectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
83 this._observer?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
84 this._control = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
85 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
86
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
87 sync() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
88 this._control = this.querySelector(this.controlSelector);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
89 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
90 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
91
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
92 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
93 * Provides presentation around a native checkbox input.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
94 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
95 * @extends {NativeControl}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
96 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
97 export class ZenCheckbox extends NativeControl {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
98 get controlSelector() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
99 return 'input[type="checkbox"]';
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
100 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
101 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
102
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
103 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
104 * Provides presentation around a native select control.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
105 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
106 * @extends {NativeControl}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
107 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
108 export class ZenSelect extends NativeControl {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
109 get controlSelector() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
110 return "select";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
111 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
112
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
113 sync() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
114 super.sync();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
115 if (!this._control) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
116 let icon = this.querySelector(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
117 ":scope > zen-icon[data-zen-select-icon]",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
118 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
119 if (!icon) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
120 icon = document.createElement("zen-icon");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
121 icon.dataset.zenSelectIcon = "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
122 icon.dataset.zenGenerated = "true";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
123 icon.setAttribute("name", "chevron-down");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
124 this.append(icon);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
125 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
126 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
127
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
128 disconnectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
129 this.querySelector(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
130 ':scope > zen-icon[data-zen-select-icon][data-zen-generated="true"]',
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
131 )?.remove();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
132 super.disconnectedCallback();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
133 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
134 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
135
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
136 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
137 * Provides presentation around a native range input.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
138 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
139 * @extends {NativeControl}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
140 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
141 export class ZenSlider extends NativeControl {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
142 get controlSelector() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
143 return 'input[type="range"]';
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
144 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
145 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
146
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
147 function createDate(year, month, day) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
148 const date = new Date(0);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
149 date.setHours(0, 0, 0, 0);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
150 date.setFullYear(year, month, day);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
151 return date;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
152 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
153
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
154 function parseDate(value) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
155 const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value || "");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
156 if (!match) return null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
157 const year = Number(match[1]);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
158 const month = Number(match[2]) - 1;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
159 const day = Number(match[3]);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
160 const date = createDate(year, month, day);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
161 if (date.getFullYear() !== year ||
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
162 date.getMonth() !== month ||
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
163 date.getDate() !== day) return null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
164 return date;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
165 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
166
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
167 function dateKey(date) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
168 const year = String(date.getFullYear()).padStart(4, "0");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
169 const month = String(date.getMonth() + 1).padStart(2, "0");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
170 const day = String(date.getDate()).padStart(2, "0");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
171 return `${year}-${month}-${day}`;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
172 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
173
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
174 function addDays(date, amount) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
175 return createDate(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
176 date.getFullYear(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
177 date.getMonth(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
178 date.getDate() + amount,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
179 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
180 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
181
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
182 function addMonths(date, amount) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
183 const first = createDate(date.getFullYear(), date.getMonth() + amount, 1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
184 const last = createDate(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
185 first.getFullYear(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
186 first.getMonth() + 1,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
187 0,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
188 ).getDate();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
189 return createDate(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
190 first.getFullYear(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
191 first.getMonth(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
192 Math.min(date.getDate(), last),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
193 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
194 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
195
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
196 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
197 * Renders a tokenized calendar backed by a native date input.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
198 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
199 * @extends {HTMLElement}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
200 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
201 export class ZenCalendar extends HTMLElement {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
202 connectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
203 this._managed ||= new Map();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
204 this._onClick ||= event => this.onClick(event);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
205 this._onKeydown ||= event => this.onKeydown(event);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
206 this._onInput ||= event => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
207 if (event.target !== this._input) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
208 this.readInput();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
209 if (this._input.validity.valid) this.setInvalid(false);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
210 this.render();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
211 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
212 this._onInvalid ||= event => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
213 if (event.target !== this._input) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
214 event.preventDefault();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
215 this.setInvalid(true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
216 queueMicrotask(() => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
217 if (!this.isConnected) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
218 const target = this._trigger ||
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
219 this._grid?.querySelector('[tabindex="0"]:not(:disabled)');
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
220 target?.focus();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
221 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
222 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
223 this._onDocumentPointerDown ||= event => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
224 if (this.isPicker && this._open && !this.contains(event.target)) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
225 this.setOpen(false);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
226 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
227 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
228 this._onReset ||= () => queueMicrotask(() => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
229 if (!this.isConnected) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
230 this.readInput();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
231 this.render();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
232 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
233 this.addEventListener("click", this._onClick);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
234 this.addEventListener("keydown", this._onKeydown);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
235 this.addEventListener("input", this._onInput);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
236 this.addEventListener("change", this._onInput);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
237 this.addEventListener("invalid", this._onInvalid, true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
238 document.addEventListener("pointerdown", this._onDocumentPointerDown);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
239 this._observer ||= new MutationObserver(() => this.sync());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
240 this._observer.observe(this, { childList: true });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
241 this._inputObserver ||= new MutationObserver(() => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
242 this.readInput();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
243 this.render();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
244 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
245 this.sync();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
246 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
247
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
248 disconnectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
249 this._observer?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
250 this._inputObserver?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
251 this._form?.removeEventListener("reset", this._onReset);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
252 this.removeEventListener("click", this._onClick);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
253 this.removeEventListener("keydown", this._onKeydown);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
254 this.removeEventListener("input", this._onInput);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
255 this.removeEventListener("change", this._onInput);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
256 this.removeEventListener("invalid", this._onInvalid, true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
257 document.removeEventListener("pointerdown", this._onDocumentPointerDown);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
258 this.release();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
259 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
260
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
261 get isPicker() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
262 return this.localName === "zen-date-picker";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
263 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
264
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
265 sync() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
266 const input = [...this.children].find(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
267 child => child.matches?.('input[type="date"]'),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
268 ) || null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
269 if (input === this._input) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
270 this.release();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
271 this._input = input;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
272 if (!input) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
273
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
274 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
275 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
276 input,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
277 "data-zen-calendar-input",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
278 "",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
279 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
280 setManagedAttribute(this._managed, input, "tabindex", "-1");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
281 setManagedAttribute(this._managed, input, "aria-hidden", "true");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
282 this._inputObserver.observe(input, {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
283 attributes: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
284 attributeFilter: ["disabled", "max", "min", "readonly", "value"],
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
285 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
286 this._form = input.form;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
287 this._form?.addEventListener("reset", this._onReset);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
288 this.readInput();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
289 this.createView();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
290 this.render();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
291 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
292
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
293 release() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
294 this._inputObserver?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
295 this._form?.removeEventListener("reset", this._onReset);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
296 this._generated?.remove();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
297 this._generated = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
298 this._view = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
299 this._grid = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
300 this._heading = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
301 this._trigger = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
302 this._panel = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
303 this._labelText = "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
304 this._labelIds = [];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
305 this._form = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
306 this._open = false;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
307 restoreAttributes(this._managed || new Map());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
308 this._input = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
309 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
310
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
311 readInput() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
312 const selected = parseDate(this._input?.value);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
313 const today = new Date();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
314 this._selected = selected;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
315 this._focusDate = selected || this._focusDate || today;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
316 this._month = createDate(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
317 (selected || this._focusDate).getFullYear(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
318 (selected || this._focusDate).getMonth(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
319 1,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
320 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
321 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
322
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
323 limits() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
324 return {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
325 maximum: parseDate(this._input?.max),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
326 minimum: parseDate(this._input?.min),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
327 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
328 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
329
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
330 isEditable() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
331 return Boolean(this._input) &&
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
332 !this._input.disabled &&
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
333 !this._input.readOnly;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
334 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
335
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
336 isAllowed(date) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
337 if (!date) return false;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
338 const { maximum, minimum } = this.limits();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
339 return (!minimum || date >= minimum) && (!maximum || date <= maximum);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
340 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
341
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
342 clampDate(date) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
343 const { maximum, minimum } = this.limits();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
344 if (minimum && date < minimum) return minimum;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
345 if (maximum && date > maximum) return maximum;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
346 return date;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
347 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
348
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
349 setInvalid(invalid) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
350 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
351 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
352 this,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
353 "data-invalid",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
354 invalid ? "" : null,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
355 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
356 if (this._trigger) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
357 this._trigger.setAttribute("aria-invalid", String(invalid));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
358 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
359 if (this._grid) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
360 this._grid.setAttribute("aria-invalid", String(invalid));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
361 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
362 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
363
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
364 createIcon(name) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
365 const icon = document.createElement("zen-icon");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
366 icon.setAttribute("name", name);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
367 return icon;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
368 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
369
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
370 createControl(name, label) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
371 const button = document.createElement("button");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
372 button.type = "button";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
373 button.dataset[name] = "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
374 button.setAttribute("aria-label", label);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
375 return button;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
376 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
377
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
378 createView() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
379 const generated = document.createElement("div");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
380 generated.dataset.zenGenerated = "calendar";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
381 this._generated = generated;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
382 const labels = [...this._input.labels];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
383 const authoredLabelIds = (this._input.getAttribute("aria-labelledby") || "")
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
384 .split(/\s+/)
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
385 .filter(id => id && document.getElementById(id));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
386 const associatedLabelIds = labels.map(label =>
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
387 ensureId(this._managed, label, "zen-date-label")
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
388 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
389 this._labelIds = authoredLabelIds.length
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
390 ? authoredLabelIds
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
391 : associatedLabelIds;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
392 this._labelText = this._labelIds.map(id =>
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
393 document.getElementById(id)?.textContent.trim()
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
394 )
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
395 .filter(Boolean)
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
396 .join(", ") ||
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
397 labels.map(label => label.textContent.trim())
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
398 .filter(Boolean)
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
399 .join(", ") ||
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
400 this._input.getAttribute("aria-label") ||
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
401 "Date";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
402
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
403 if (this.isPicker) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
404 const trigger = this.createControl(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
405 "zenDateTrigger",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
406 "Choose date",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
407 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
408 trigger.id = uniqueId("zen-date-picker-trigger");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
409 trigger.append(this.createIcon("calendar"));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
410 const triggerText = document.createElement("span");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
411 triggerText.dataset.zenDateValue = "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
412 triggerText.id = uniqueId("zen-date-picker-value");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
413 trigger.append(triggerText);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
414 this._trigger = trigger;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
415
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
416 const panel = document.createElement("div");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
417 panel.dataset.zenCalendarPanel = "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
418 panel.id = uniqueId("zen-date-picker-panel");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
419 panel.setAttribute("role", "dialog");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
420 panel.setAttribute("aria-label", `${this._labelText} calendar`);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
421 panel.hidden = true;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
422 trigger.setAttribute("aria-haspopup", "dialog");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
423 trigger.setAttribute("aria-controls", panel.id);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
424 if (this._input.hasAttribute("aria-describedby")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
425 trigger.setAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
426 "aria-describedby",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
427 this._input.getAttribute("aria-describedby"),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
428 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
429 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
430 if (this._labelIds.length) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
431 trigger.setAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
432 "aria-labelledby",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
433 [...this._labelIds, triggerText.id].join(" "),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
434 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
435 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
436 for (const label of labels) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
437 if (label.htmlFor === this._input.id) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
438 setManagedAttribute(this._managed, label, "for", trigger.id);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
439 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
440 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
441 this._panel = panel;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
442 generated.append(trigger, panel);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
443 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
444
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
445 const view = document.createElement("div");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
446 view.dataset.zenCalendarView = "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
447 const header = document.createElement("header");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
448 const previous = this.createControl(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
449 "zenCalendarPrevious",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
450 "Previous month",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
451 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
452 previous.append(this.createIcon("chevron-left"));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
453 const heading = document.createElement("strong");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
454 heading.setAttribute("aria-live", "polite");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
455 const next = this.createControl("zenCalendarNext", "Next month");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
456 next.append(this.createIcon("chevron-right"));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
457 header.append(previous, heading, next);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
458
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
459 const weekdays = document.createElement("div");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
460 weekdays.dataset.zenCalendarWeekdays = "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
461 weekdays.setAttribute("aria-hidden", "true");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
462 const formatter = new Intl.DateTimeFormat(undefined, {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
463 weekday: "narrow",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
464 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
465 for (let day = 4; day < 11; day++) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
466 const label = document.createElement("span");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
467 label.textContent = formatter.format(new Date(2026, 0, day));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
468 weekdays.append(label);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
469 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
470
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
471 const grid = document.createElement("div");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
472 grid.dataset.zenCalendarGrid = "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
473 grid.setAttribute("role", "grid");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
474 grid.setAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
475 "aria-label",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
476 this._labelText ? `${this._labelText} calendar` : "Calendar",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
477 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
478 view.append(header, weekdays, grid);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
479 this._view = view;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
480 this._heading = heading;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
481 this._grid = grid;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
482 (this._panel || generated).append(view);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
483 this.append(generated);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
484 if (this.isPicker) this.setOpen(false);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
485 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
486
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
487 render() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
488 if (!this._grid || !this._month) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
489 this._focusDate = this.clampDate(this._focusDate);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
490 this._heading.textContent = new Intl.DateTimeFormat(undefined, {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
491 month: "long",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
492 year: "numeric",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
493 }).format(this._month);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
494
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
495 if (this._trigger) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
496 const text = this._trigger.querySelector("[data-zen-date-value]");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
497 text.textContent = this._selected
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
498 ? new Intl.DateTimeFormat(undefined, {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
499 dateStyle: "medium",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
500 }).format(this._selected)
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
501 : "Choose date";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
502 if (this._labelIds.length) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
503 this._trigger.removeAttribute("aria-label");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
504 } else {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
505 this._trigger.setAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
506 "aria-label",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
507 `${this._labelText}, ${text.textContent}`,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
508 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
509 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
510 this._trigger.disabled = !this.isEditable();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
511 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
512 for (const control of this._view.querySelectorAll(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
513 "[data-zen-calendar-previous], [data-zen-calendar-next]",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
514 )) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
515 control.disabled = !this.isEditable();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
516 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
517
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
518 const first = createDate(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
519 this._month.getFullYear(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
520 this._month.getMonth(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
521 1,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
522 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
523 const start = addDays(first, -first.getDay());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
524 const { maximum, minimum } = this.limits();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
525 const today = dateKey(new Date());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
526 const selected = this._selected ? dateKey(this._selected) : "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
527 const focused = dateKey(this._focusDate);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
528 const fragment = document.createDocumentFragment();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
529 const formatter = new Intl.DateTimeFormat(undefined, {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
530 dateStyle: "full",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
531 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
532
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
533 for (let week = 0; week < 6; week++) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
534 const row = document.createElement("div");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
535 row.setAttribute("role", "row");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
536 for (let day = 0; day < 7; day++) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
537 const date = addDays(start, week * 7 + day);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
538 const key = dateKey(date);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
539 const button = document.createElement("button");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
540 button.type = "button";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
541 button.dataset.zenCalendarDay = key;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
542 button.setAttribute("role", "gridcell");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
543 button.setAttribute("aria-label", formatter.format(date));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
544 button.setAttribute("aria-selected", String(key === selected));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
545 const disabled = !this.isEditable() ||
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
546 Boolean((minimum && date < minimum) || (maximum && date > maximum));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
547 button.tabIndex = key === focused && !disabled ? 0 : -1;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
548 button.textContent = String(date.getDate());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
549 button.toggleAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
550 "data-outside",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
551 date.getMonth() !== this._month.getMonth(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
552 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
553 button.toggleAttribute("data-today", key === today);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
554 button.disabled = disabled;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
555 row.append(button);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
556 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
557 fragment.append(row);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
558 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
559 this._grid.replaceChildren(fragment);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
560 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
561
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
562 onClick(event) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
563 const target = event.target instanceof Element ? event.target : null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
564 if (!target) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
565 if (target.closest("[data-zen-date-trigger]") === this._trigger) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
566 if (!this.isEditable()) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
567 this.setOpen(!this._open);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
568 return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
569 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
570 if (target.closest("[data-zen-calendar-previous]")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
571 if (!this.isEditable()) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
572 this.changeMonth(-1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
573 return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
574 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
575 if (target.closest("[data-zen-calendar-next]")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
576 if (!this.isEditable()) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
577 this.changeMonth(1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
578 return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
579 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
580 const day = target.closest("[data-zen-calendar-day]");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
581 if (day && !day.disabled) this.selectDate(parseDate(day.dataset.zenCalendarDay));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
582 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
583
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
584 onKeydown(event) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
585 if (event.key === "Escape" && this.isPicker && this._open) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
586 event.preventDefault();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
587 this.setOpen(false);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
588 this._trigger.focus();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
589 return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
590 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
591 const day = event.target instanceof Element
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
592 ? event.target.closest("[data-zen-calendar-day]")
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
593 : null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
594 if (!day) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
595 const current = parseDate(day.dataset.zenCalendarDay);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
596 let next = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
597 if (event.key === "ArrowLeft") next = addDays(current, -1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
598 else if (event.key === "ArrowRight") next = addDays(current, 1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
599 else if (event.key === "ArrowUp") next = addDays(current, -7);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
600 else if (event.key === "ArrowDown") next = addDays(current, 7);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
601 else if (event.key === "Home") next = addDays(current, -current.getDay());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
602 else if (event.key === "End") next = addDays(current, 6 - current.getDay());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
603 else if (event.key === "PageUp") next = addMonths(current, -1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
604 else if (event.key === "PageDown") next = addMonths(current, 1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
605 if (!next) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
606 next = this.clampDate(next);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
607 event.preventDefault();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
608 this._focusDate = next;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
609 this._month = createDate(next.getFullYear(), next.getMonth(), 1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
610 this.render();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
611 this._grid.querySelector(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
612 `[data-zen-calendar-day="${dateKey(next)}"]`,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
613 )?.focus();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
614 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
615
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
616 changeMonth(amount) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
617 if (!this.isEditable()) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
618 this._month = addMonths(this._month, amount);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
619 this._focusDate = this.clampDate(createDate(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
620 this._month.getFullYear(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
621 this._month.getMonth(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
622 1,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
623 ));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
624 this._month = createDate(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
625 this._focusDate.getFullYear(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
626 this._focusDate.getMonth(),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
627 1,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
628 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
629 this.render();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
630 this._grid.querySelector('[tabindex="0"]')?.focus();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
631 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
632
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
633 selectDate(date) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
634 if (!this.isEditable() || !this.isAllowed(date)) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
635 this._selected = date;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
636 this._focusDate = date;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
637 this._month = createDate(date.getFullYear(), date.getMonth(), 1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
638 this._input.value = dateKey(date);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
639 this._input.dispatchEvent(new Event("input", {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
640 bubbles: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
641 composed: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
642 }));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
643 this._input.dispatchEvent(new Event("change", { bubbles: true }));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
644 emit(this, "zen-change", { value: this._input.value });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
645 this.render();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
646 if (this.isPicker) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
647 this.setOpen(false);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
648 this._trigger.focus();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
649 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
650 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
651
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
652 setOpen(open) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
653 if (!this.isPicker || !this._panel || !this._trigger) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
654 this._open = Boolean(open) && this.isEditable();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
655 this._panel.hidden = !this._open;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
656 this._trigger.setAttribute("aria-expanded", String(this._open));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
657 if (this._open) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
658 this._grid.querySelector('[tabindex="0"]')?.focus();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
659 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
660 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
661 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
662
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
663 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
664 * Presents the first-party calendar behind a tokenized disclosure trigger.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
665 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
666 * @extends {ZenCalendar}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
667 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
668 export class ZenDatePicker extends ZenCalendar {}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
669
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
670 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
671 * Adds radiogroup semantics when no native fieldset owns the radios.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
672 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
673 * @extends {HTMLElement}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
674 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
675 export class ZenRadioGroup extends HTMLElement {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
676 connectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
677 this._managed ||= new Map();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
678 if (!this._observer) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
679 this._observer = new MutationObserver(() => this.sync());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
680 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
681 this._observer.observe(this, { childList: true, subtree: true });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
682 this.sync();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
683 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
684
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
685 disconnectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
686 this._observer?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
687 restoreAttributes(this._managed);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
688 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
689
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
690 sync() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
691 const radios = this.querySelectorAll('input[type="radio"]');
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
692 const needsRole = radios.length > 0 && !this.querySelector("fieldset");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
693 if (needsRole && !this.hasAttribute("role")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
694 setManagedAttribute(this._managed, this, "role", "radiogroup");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
695 } else if (!needsRole) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
696 restoreElement(this._managed, this);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
697 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
698 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
699 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
700
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
701 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
702 * Synchronizes switch semantics onto a native checkbox.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
703 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
704 * @extends {HTMLElement}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
705 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
706 export class ZenSwitch extends HTMLElement {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
707 connectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
708 this._managed ||= new Map();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
709 this._onStateChange ||= event => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
710 if (event.target === this._control) this.updateState();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
711 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
712 this._onReset ||= () => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
713 queueMicrotask(() => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
714 if (this.isConnected) this.updateState();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
715 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
716 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
717 this.addEventListener("input", this._onStateChange);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
718 this.addEventListener("change", this._onStateChange);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
719 if (!this._observer) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
720 this._observer = new MutationObserver(() => this.sync());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
721 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
722 this._observer.observe(this, { childList: true, subtree: true });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
723 this.sync();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
724 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
725
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
726 disconnectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
727 this._observer?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
728 this.removeEventListener("input", this._onStateChange);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
729 this.removeEventListener("change", this._onStateChange);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
730 this._form?.removeEventListener("reset", this._onReset);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
731 restoreAttributes(this._managed);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
732 this._control = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
733 this._form = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
734 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
735
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
736 sync() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
737 const control = this.querySelector('input[type="checkbox"]');
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
738 const form = control?.form || null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
739 if (control !== this._control) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
740 if (this._control) restoreElement(this._managed, this._control);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
741 this._control = control;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
742 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
743 if (form !== this._form) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
744 this._form?.removeEventListener("reset", this._onReset);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
745 this._form = form;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
746 form?.addEventListener("reset", this._onReset);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
747 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
748 this.updateState();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
749 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
750
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
751 updateState() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
752 if (!this._control) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
753 setManagedAttribute(this._managed, this._control, "role", "switch");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
754 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
755 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
756 this._control,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
757 "aria-checked",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
758 String(this._control.checked),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
759 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
760 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
761 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
762
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
763 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
764 * Reflects native form validity on the component boundary.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
765 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
766 * @extends {HTMLElement}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
767 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
768 export class ZenForm extends HTMLElement {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
769 connectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
770 this._managed ||= new Map();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
771 this._syncValidity ||= () => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
772 if (!this._form) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
773 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
774 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
775 this,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
776 "data-invalid",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
777 this._form.checkValidity() ? null : "",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
778 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
779 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
780 this._markInvalid ||= () => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
781 setManagedAttribute(this._managed, this, "data-invalid", "");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
782 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
783 this._onReset ||= () => queueMicrotask(this._syncValidity);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
784 if (!this._observer) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
785 this._observer = new MutationObserver(() => this.sync());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
786 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
787 this._observer.observe(this, { childList: true, subtree: true });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
788 this.sync();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
789 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
790
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
791 disconnectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
792 this._observer?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
793 this.releaseForm();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
794 restoreAttributes(this._managed);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
795 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
796
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
797 releaseForm() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
798 this._form?.removeEventListener("submit", this._syncValidity);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
799 this._form?.removeEventListener("input", this._syncValidity);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
800 this._form?.removeEventListener("invalid", this._markInvalid, true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
801 this._form?.removeEventListener("reset", this._onReset);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
802 this._form = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
803 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
804
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
805 sync() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
806 const form = this.querySelector("form");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
807 if (form === this._form) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
808 this.releaseForm();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
809 restoreElement(this._managed, this);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
810 this._form = form;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
811 form?.addEventListener("submit", this._syncValidity);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
812 form?.addEventListener("input", this._syncValidity);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
813 form?.addEventListener("invalid", this._markInvalid, true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
814 form?.addEventListener("reset", this._onReset);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
815 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
816 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
817
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
818 class FilterableList extends HTMLElement {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
819 connectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
820 this._managed ||= new Map();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
821 this._active = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
822 this._onInput ||= event => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
823 if (event.target !== this._input) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
824 if (this.isCombobox) this.setOpen(true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
825 this.filter();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
826 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
827 this._onKeydown ||= event => this.onKeydown(event);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
828 this._onClick ||= event => this.onClick(event);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
829 this._onFocus ||= event => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
830 if (this.isCombobox && event.target === this._input) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
831 this.setOpen(true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
832 this.filter();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
833 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
834 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
835 this.addEventListener("input", this._onInput);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
836 this.addEventListener("keydown", this._onKeydown);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
837 this.addEventListener("click", this._onClick);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
838 this.addEventListener("focusin", this._onFocus);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
839 if (!this._observer) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
840 this._observer = new MutationObserver(() => this.sync());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
841 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
842 this._observer.observe(this, { childList: true, subtree: true });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
843 this.sync();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
844 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
845
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
846 disconnectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
847 this._observer?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
848 this.removeEventListener("input", this._onInput);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
849 this.removeEventListener("keydown", this._onKeydown);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
850 this.removeEventListener("click", this._onClick);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
851 this.removeEventListener("focusin", this._onFocus);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
852 restoreAttributes(this._managed);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
853 this._input = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
854 this._list = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
855 this._items = [];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
856 this._active = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
857 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
858
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
859 get isCombobox() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
860 return false;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
861 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
862
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
863 get listRole() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
864 return "menu";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
865 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
866
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
867 get itemRole() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
868 return "menuitem";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
869 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
870
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
871 sync() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
872 const input = this.querySelector("input");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
873 const list = this.querySelector(`[role="${this.listRole}"]`);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
874 if (input !== this._input || list !== this._list) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
875 restoreAttributes(this._managed);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
876 this._input = input;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
877 this._list = list;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
878 this._items = [];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
879 this._active = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
880 this._open = false;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
881 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
882 if (!input || !list) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
883
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
884 const items = [...list.querySelectorAll(`[role="${this.itemRole}"]`)];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
885 for (const item of this._items) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
886 if (!items.includes(item)) restoreElement(this._managed, item);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
887 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
888 this._items = items;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
889
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
890 const listId = ensureId(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
891 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
892 list,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
893 this.isCombobox ? "zen-listbox" : "zen-command-menu",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
894 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
895 if (!input.hasAttribute("aria-controls")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
896 setManagedAttribute(this._managed, input, "aria-controls", listId);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
897 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
898 if (this.isCombobox) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
899 if (!input.hasAttribute("role")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
900 setManagedAttribute(this._managed, input, "role", "combobox");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
901 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
902 if (!input.hasAttribute("aria-autocomplete")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
903 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
904 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
905 input,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
906 "aria-autocomplete",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
907 "list",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
908 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
909 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
910 this.setOpen(this._open);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
911 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
912 this.filter();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
913 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
914
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
915 filter() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
916 if (!this._input || !this._list) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
917 const query = this._input.value.trim().toLowerCase();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
918 for (const item of this._items) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
919 const originallyHidden =
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
920 originalAttribute(this._managed, item, "hidden") !== null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
921 const matches = item.textContent.toLowerCase().includes(query);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
922 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
923 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
924 item,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
925 "hidden",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
926 originallyHidden || !matches ? "" : null,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
927 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
928 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
929 if (this._active?.hidden) this.setActive(null);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
930 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
931
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
932 visibleItems() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
933 return this._items.filter(item => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
934 if (item.hidden || item.closest("[hidden]")) return false;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
935 if (item.getAttribute("aria-disabled") === "true") return false;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
936 return !("disabled" in item && item.disabled);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
937 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
938 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
939
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
940 setActive(item) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
941 this._active = item;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
942 for (const candidate of this._items) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
943 if (this.isCombobox) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
944 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
945 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
946 candidate,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
947 "aria-selected",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
948 String(candidate === item),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
949 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
950 } else {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
951 restoreAttribute(this._managed, candidate, "aria-selected");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
952 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
953 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
954 if (!this._input) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
955 if (item) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
956 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
957 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
958 this._input,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
959 "aria-activedescendant",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
960 ensureId(this._managed, item, "zen-option"),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
961 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
962 item.scrollIntoView?.({ block: "nearest" });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
963 } else {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
964 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
965 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
966 this._input,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
967 "aria-activedescendant",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
968 null,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
969 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
970 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
971 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
972
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
973 moveActive(offset) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
974 const items = this.visibleItems();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
975 if (!items.length) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
976 this.setActive(null);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
977 return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
978 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
979 const current = items.indexOf(this._active);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
980 const index = current < 0
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
981 ? (offset > 0 ? 0 : items.length - 1)
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
982 : (current + offset + items.length) % items.length;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
983 this.setActive(items[index]);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
984 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
985
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
986 onKeydown(event) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
987 if (event.target !== this._input) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
988 if (event.key === "ArrowDown" || event.key === "ArrowUp") {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
989 event.preventDefault();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
990 if (this.isCombobox) this.setOpen(true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
991 this.moveActive(event.key === "ArrowDown" ? 1 : -1);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
992 return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
993 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
994 if (event.key === "Enter") {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
995 const item = this._active || this.visibleItems()[0];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
996 if (!item) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
997 event.preventDefault();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
998 this.choose(item);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
999 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1000 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1001
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1002 onClick(event) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1003 const target = event.target instanceof Element
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1004 ? event.target.closest(`[role="${this.itemRole}"]`)
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1005 : null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1006 if (!target || !this._list?.contains(target) || target.hidden) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1007 if (target.getAttribute("aria-disabled") === "true" ||
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1008 ("disabled" in target && target.disabled)) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1009 this.choose(target);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1010 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1011
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1012 valueFor(item) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1013 return item.dataset.value ?? item.getAttribute("value") ??
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1014 item.textContent.trim();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1015 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1016 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1017
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1018 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1019 * Filters and selects native option elements from a text input.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1020 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1021 * @extends {FilterableList}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1022 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1023 export class ZenCombobox extends FilterableList {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1024 get isCombobox() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1025 return true;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1026 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1027
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1028 get listRole() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1029 return "listbox";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1030 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1031
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1032 get itemRole() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1033 return "option";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1034 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1035
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1036 setOpen(open) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1037 this._open = Boolean(open);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1038 if (!this._input || !this._list) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1039 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1040 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1041 this._input,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1042 "aria-expanded",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1043 String(this._open),
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1044 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1045 setManagedAttribute(
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1046 this._managed,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1047 this._list,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1048 "hidden",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1049 this._open ? null : "",
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1050 );
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1051 if (!this._open) this.setActive(null);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1052 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1053
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1054 onKeydown(event) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1055 if (event.target === this._input && event.key === "Escape") {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1056 if (this._open) event.preventDefault();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1057 this.setOpen(false);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1058 return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1059 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1060 super.onKeydown(event);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1061 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1062
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1063 choose(item) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1064 const value = this.valueFor(item);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1065 this._input.value = value;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1066 this._input.dispatchEvent(new Event("input", {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1067 bubbles: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1068 composed: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1069 }));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1070 this._input.dispatchEvent(new Event("change", { bubbles: true }));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1071 emit(this, "zen-change", { value });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1072 this.setOpen(false);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1073 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1074 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1075
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1076 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1077 * Filters a keyboard-oriented command menu and emits selected commands.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1078 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1079 * @extends {FilterableList}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1080 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1081 export class ZenCommand extends FilterableList {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1082 choose(item) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1083 emit(this, "zen-command", { value: this.valueFor(item) });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1084 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1085 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1086
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1087 /**
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1088 * Enhances one native one-time-code input with visual slots.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1089 *
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1090 * @extends {HTMLElement}
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1091 */
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1092 export class ZenInputOtp extends HTMLElement {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1093 connectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1094 this._managed ||= new Map();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1095 this._complete ??= false;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1096 this._onInput ||= event => {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1097 if (event.target === this._input) this.update(true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1098 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1099 this.addEventListener("input", this._onInput);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1100 if (!this._observer) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1101 this._observer = new MutationObserver(() => this.sync());
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1102 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1103 this._observer.observe(this, {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1104 attributes: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1105 attributeFilter: ["allow", "maxlength", "pattern"],
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1106 childList: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1107 subtree: true,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1108 });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1109 this.sync();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1110 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1111
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1112 disconnectedCallback() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1113 this._observer?.disconnect();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1114 this.removeEventListener("input", this._onInput);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1115 const input = this._input;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1116 const complete = this._complete;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1117 this.release();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1118 this._previousInput = input;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1119 this._complete = complete;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1120 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1121
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1122 release() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1123 restoreAttributes(this._managed);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1124 if (this._slots && this._originalSlots) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1125 this._slots.replaceChildren(...this._originalSlots);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1126 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1127 this._input = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1128 this._slots = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1129 this._originalSlots = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1130 this._complete = false;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1131 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1132
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1133 sync() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1134 const inputs = [...this.querySelectorAll("input")];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1135 const input = inputs.length === 1 ? inputs[0] : null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1136 const slots = this.querySelector("[data-zen-otp-slots]");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1137 if (input !== this._input || slots !== this._slots) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1138 const remainedComplete =
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1139 (input === this._input || input === this._previousInput) &&
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1140 this._complete;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1141 this.release();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1142 this._input = input;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1143 this._slots = slots;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1144 this._originalSlots = slots ? [...slots.childNodes] : null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1145 this._complete = remainedComplete;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1146 this._previousInput = null;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1147 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1148 if (!this._input) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1149
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1150 if (!this._input.hasAttribute("maxlength")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1151 setManagedAttribute(this._managed, this._input, "maxlength", "6");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1152 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1153 if (this.numericOnly() && !this._input.hasAttribute("inputmode")) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1154 setManagedAttribute(this._managed, this._input, "inputmode", "numeric");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1155 } else if (!this.numericOnly()) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1156 restoreAttribute(this._managed, this._input, "inputmode");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1157 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1158 this.update(true);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1159 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1160
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1161 numericOnly() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1162 return !this.hasAttribute("allow") &&
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1163 !this.hasAttribute("pattern") &&
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1164 !this._input.hasAttribute("allow") &&
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1165 !this._input.hasAttribute("pattern");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1166 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1167
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1168 length() {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1169 const value = Number.parseInt(this._input.getAttribute("maxlength"), 10);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1170 return Number.isFinite(value) && value > 0 ? value : 6;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1171 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1172
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1173 update(notify) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1174 const length = this.length();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1175 const before = this._input.value;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1176 let value = this.numericOnly() ? before.replace(/\D/g, "") : before;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1177 value = [...value].slice(0, length).join("");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1178 if (value !== before) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1179 const selection = this._input.selectionStart;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1180 this._input.value = value;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1181 if (selection !== null) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1182 const preceding = before.slice(0, selection);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1183 const position = this.numericOnly()
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1184 ? preceding.replace(/\D/g, "").length
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1185 : [...preceding].slice(0, length).join("").length;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1186 try {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1187 this._input.setSelectionRange(position, position);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1188 } catch {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1189 // Some native input types do not expose text selection.
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1190 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1191 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1192 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1193 this.renderSlots(value, length);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1194
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1195 const complete = [...value].length === length;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1196 if (notify && complete && !this._complete) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1197 emit(this, "zen-complete", { value });
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1198 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1199 this._complete = complete;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1200 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1201
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1202 renderSlots(value, length) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1203 if (!this._slots) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1204 const characters = [...value];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1205 const current = [...this._slots.children];
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1206 const unchanged = current.length === length &&
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1207 current.every((slot, index) =>
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1208 slot.localName === "span" &&
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1209 slot.textContent === (characters[index] || ""));
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1210 if (unchanged) return;
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1211
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1212 const fragment = document.createDocumentFragment();
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1213 for (let index = 0; index < length; index++) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1214 const slot = document.createElement("span");
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1215 slot.textContent = characters[index] || "";
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1216 fragment.append(slot);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1217 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1218 this._slots.replaceChildren(fragment);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1219 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1220 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1221
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1222 const definitions = {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1223 "zen-calendar": ZenCalendar,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1224 "zen-checkbox": ZenCheckbox,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1225 "zen-combobox": ZenCombobox,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1226 "zen-command": ZenCommand,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1227 "zen-date-picker": ZenDatePicker,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1228 "zen-form": ZenForm,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1229 "zen-input-otp": ZenInputOtp,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1230 "zen-radio-group": ZenRadioGroup,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1231 "zen-select": ZenSelect,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1232 "zen-slider": ZenSlider,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1233 "zen-switch": ZenSwitch,
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1234 };
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1235
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1236 if (globalThis.customElements) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1237 for (const [name, definition] of Object.entries(definitions)) {
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1238 if (!customElements.get(name)) customElements.define(name, definition);
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1239 }
2b6e732087ff [ui] Add complete native component catalog
MrJuneJune <me@mrjunejune.com>
parents:
diff changeset
1240 }