@adia-ai/web-components 0.6.33 → 0.6.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/components/accordion/accordion.css +2 -2
- package/components/action-list/action-list.css +2 -2
- package/components/agent-artifact/agent-artifact.css +31 -31
- package/components/agent-feedback-bar/agent-feedback-bar.css +10 -10
- package/components/agent-questions/agent-questions.css +57 -57
- package/components/agent-reasoning/agent-reasoning.css +62 -62
- package/components/agent-suggestions/agent-suggestions.css +4 -4
- package/components/agent-trace/agent-trace.css +53 -53
- package/components/alert/alert.css +41 -41
- package/components/avatar/avatar.css +27 -27
- package/components/badge/badge.css +27 -27
- package/components/block/block.css +16 -16
- package/components/breadcrumb/breadcrumb.css +23 -23
- package/components/button/button.css +101 -91
- package/components/calendar-grid/calendar-grid.a2ui.json +136 -0
- package/components/calendar-grid/calendar-grid.css +226 -0
- package/components/calendar-grid/calendar-grid.d.ts +37 -0
- package/components/calendar-grid/calendar-grid.js +17 -0
- package/components/calendar-grid/calendar-grid.yaml +116 -0
- package/components/calendar-grid/class.js +300 -0
- package/components/calendar-picker/calendar-picker.css +139 -139
- package/components/canvas/canvas.css +12 -12
- package/components/card/card.css +83 -83
- package/components/chart/chart.css +224 -224
- package/components/chart-legend/chart-legend.css +26 -26
- package/components/check/check.css +40 -40
- package/components/code/code.css +125 -125
- package/components/col/col.css +15 -15
- package/components/color-picker/color-picker.css +55 -55
- package/components/combobox/class.js +861 -0
- package/components/combobox/combobox.a2ui.json +363 -0
- package/components/combobox/combobox.css +244 -0
- package/components/combobox/combobox.d.ts +113 -0
- package/components/combobox/combobox.examples.md +59 -0
- package/components/combobox/combobox.js +17 -0
- package/components/combobox/combobox.test.js +181 -0
- package/components/combobox/combobox.yaml +369 -0
- package/components/command/command.css +90 -90
- package/components/date-range-picker/class.js +775 -0
- package/components/date-range-picker/date-range-picker.a2ui.json +300 -0
- package/components/date-range-picker/date-range-picker.css +178 -0
- package/components/date-range-picker/date-range-picker.d.ts +82 -0
- package/components/date-range-picker/date-range-picker.examples.md +37 -0
- package/components/date-range-picker/date-range-picker.js +17 -0
- package/components/date-range-picker/date-range-picker.test.js +387 -0
- package/components/date-range-picker/date-range-picker.yaml +285 -0
- package/components/datetime-picker/class.js +706 -0
- package/components/datetime-picker/datetime-picker.a2ui.json +334 -0
- package/components/datetime-picker/datetime-picker.css +150 -0
- package/components/datetime-picker/datetime-picker.d.ts +86 -0
- package/components/datetime-picker/datetime-picker.examples.md +46 -0
- package/components/datetime-picker/datetime-picker.js +17 -0
- package/components/datetime-picker/datetime-picker.test.js +454 -0
- package/components/datetime-picker/datetime-picker.yaml +332 -0
- package/components/demo-toggle/demo-toggle.css +27 -27
- package/components/description-list/description-list.css +18 -18
- package/components/divider/divider.css +24 -24
- package/components/embed/embed.css +6 -6
- package/components/empty-state/empty-state.css +27 -27
- package/components/feed/feed.css +12 -12
- package/components/field/field.css +28 -28
- package/components/fields/fields.css +5 -5
- package/components/grid/grid.css +5 -5
- package/components/heatmap/heatmap.css +63 -63
- package/components/icon/icon.css +12 -12
- package/components/image/image.css +14 -14
- package/components/index.js +8 -0
- package/components/input/input.css +66 -66
- package/components/inspector/inspector.css +6 -6
- package/components/integration-card/class.js +410 -0
- package/components/integration-card/integration-card.a2ui.json +268 -0
- package/components/integration-card/integration-card.css +169 -0
- package/components/integration-card/integration-card.d.ts +63 -0
- package/components/integration-card/integration-card.examples.md +41 -0
- package/components/integration-card/integration-card.js +17 -0
- package/components/integration-card/integration-card.test.js +306 -0
- package/components/integration-card/integration-card.yaml +280 -0
- package/components/kbd/kbd.css +32 -32
- package/components/link/link.css +12 -12
- package/components/list/list.css +8 -8
- package/components/list-window/class.js +688 -0
- package/components/list-window/list-window.a2ui.json +277 -0
- package/components/list-window/list-window.css +124 -0
- package/components/list-window/list-window.d.ts +84 -0
- package/components/list-window/list-window.examples.md +73 -0
- package/components/list-window/list-window.js +17 -0
- package/components/list-window/list-window.test.js +303 -0
- package/components/list-window/list-window.yaml +270 -0
- package/components/menu/menu.css +8 -8
- package/components/modal/modal.css +43 -43
- package/components/nav/nav.css +40 -40
- package/components/nav-group/nav-group.css +52 -52
- package/components/nav-item/nav-item.css +44 -44
- package/components/noodles/noodles.css +31 -31
- package/components/option-card/option-card.css +69 -69
- package/components/otp-input/otp-input.css +30 -30
- package/components/page/page.css +18 -18
- package/components/pagination/pagination.css +61 -61
- package/components/pane/pane.css +57 -57
- package/components/pipeline-status/pipeline-status.css +65 -65
- package/components/popover/popover.css +17 -17
- package/components/progress/progress.css +23 -23
- package/components/progress-row/progress-row.css +17 -17
- package/components/radio/radio.css +39 -39
- package/components/range/range.css +55 -55
- package/components/rating/rating.css +28 -28
- package/components/richtext/richtext.css +133 -133
- package/components/row/row.css +19 -19
- package/components/search/search.css +5 -5
- package/components/segment/segment.css +24 -24
- package/components/segmented/segmented.css +25 -25
- package/components/select/select.css +84 -84
- package/components/skeleton/skeleton.css +14 -14
- package/components/slider/slider.css +46 -46
- package/components/spinner/class.js +69 -0
- package/components/spinner/spinner.a2ui.json +197 -0
- package/components/spinner/spinner.css +165 -0
- package/components/spinner/spinner.d.ts +26 -0
- package/components/spinner/spinner.examples.md +26 -0
- package/components/spinner/spinner.js +17 -0
- package/components/spinner/spinner.test.js +234 -0
- package/components/spinner/spinner.yaml +230 -0
- package/components/stack/stack.css +11 -11
- package/components/stat/stat.css +25 -25
- package/components/step-progress/step-progress.css +20 -20
- package/components/stepper/stepper.css +29 -29
- package/components/stream/stream.css +12 -12
- package/components/swatch/swatch.css +68 -68
- package/components/swiper/swiper.css +57 -57
- package/components/switch/switch.css +52 -52
- package/components/table/table.css +162 -162
- package/components/table-toolbar/table-toolbar.css +32 -32
- package/components/tabs/tabs.css +51 -51
- package/components/tag/tag.css +48 -48
- package/components/text/text.css +44 -44
- package/components/textarea/textarea.css +46 -46
- package/components/time-picker/class.js +693 -0
- package/components/time-picker/time-picker.a2ui.json +267 -0
- package/components/time-picker/time-picker.css +122 -0
- package/components/time-picker/time-picker.d.ts +75 -0
- package/components/time-picker/time-picker.examples.md +35 -0
- package/components/time-picker/time-picker.js +17 -0
- package/components/time-picker/time-picker.test.js +287 -0
- package/components/time-picker/time-picker.yaml +256 -0
- package/components/timeline/timeline.css +50 -50
- package/components/toast/toast.css +58 -58
- package/components/toggle-group/toggle-group.css +6 -6
- package/components/toggle-scheme/toggle-scheme.css +2 -2
- package/components/toolbar/toolbar.css +17 -17
- package/components/tooltip/tooltip.css +2 -2
- package/components/tree/tree.css +37 -37
- package/components/upload/upload.css +49 -49
- package/dist/web-components.min.css +1 -1
- package/dist/web-components.min.js +121 -83
- package/package.json +1 -1
- package/styles/components.css +8 -0
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/TimePicker.json",
|
|
4
|
+
"title": "TimePicker",
|
|
5
|
+
"description": "Time-of-day picker with discrete segments (hour, minute, optional second, optional AM/PM). Each segment follows the WAI-ARIA Spinbutton pattern with Arrow-key increment/decrement, Page Up/Down for larger jumps, Home/End for segment min/max, and Tab to move between segments. Form-associated input emitting ISO 8601 time string (\"HH:mm\" or \"HH:mm:ss\") via change events. Per ADR-0025 no native form controls — segments are contenteditable spans inside a custom host. SPEC-043.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"required": {
|
|
17
|
+
"description": "Marks the field as required for form validation. Sets aria-required.",
|
|
18
|
+
"type": "boolean",
|
|
19
|
+
"default": false
|
|
20
|
+
},
|
|
21
|
+
"component": {
|
|
22
|
+
"const": "TimePicker"
|
|
23
|
+
},
|
|
24
|
+
"disabled": {
|
|
25
|
+
"description": "Disables interaction; dims the control",
|
|
26
|
+
"type": "boolean",
|
|
27
|
+
"default": false
|
|
28
|
+
},
|
|
29
|
+
"hourcycle": {
|
|
30
|
+
"description": "Hour cycle. Empty (default) derives from the document locale — most\nen-* locales resolve to `h23`. `h12` forces a 12-hour cycle with an\nAM/PM (meridiem) segment; `h23` forces 24-hour cycle.\n",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"enum": [
|
|
33
|
+
"",
|
|
34
|
+
"h12",
|
|
35
|
+
"h23"
|
|
36
|
+
],
|
|
37
|
+
"default": ""
|
|
38
|
+
},
|
|
39
|
+
"locale": {
|
|
40
|
+
"description": "BCP-47 locale tag used to derive hour-cycle when `hour-cycle` is empty. Falls back to `<html lang>` then to browser default.",
|
|
41
|
+
"type": "string",
|
|
42
|
+
"default": ""
|
|
43
|
+
},
|
|
44
|
+
"max": {
|
|
45
|
+
"description": "Latest selectable time as ISO 8601. Empty disables the constraint.",
|
|
46
|
+
"type": "string",
|
|
47
|
+
"default": ""
|
|
48
|
+
},
|
|
49
|
+
"min": {
|
|
50
|
+
"description": "Earliest selectable time as ISO 8601. Empty disables the constraint.",
|
|
51
|
+
"type": "string",
|
|
52
|
+
"default": ""
|
|
53
|
+
},
|
|
54
|
+
"name": {
|
|
55
|
+
"description": "Form field name for FormData submission",
|
|
56
|
+
"type": "string",
|
|
57
|
+
"default": ""
|
|
58
|
+
},
|
|
59
|
+
"placeholder": {
|
|
60
|
+
"description": "Per-segment placeholder text shown when a segment is empty. Defaults to \"--\".",
|
|
61
|
+
"type": "string",
|
|
62
|
+
"default": "--"
|
|
63
|
+
},
|
|
64
|
+
"precision": {
|
|
65
|
+
"description": "Whether the seconds segment is exposed. `minute` (default) hides seconds; `second` adds the seconds segment + separator.",
|
|
66
|
+
"type": "string",
|
|
67
|
+
"enum": [
|
|
68
|
+
"minute",
|
|
69
|
+
"second"
|
|
70
|
+
],
|
|
71
|
+
"default": "minute"
|
|
72
|
+
},
|
|
73
|
+
"readonly": {
|
|
74
|
+
"description": "Prevents editing while keeping the field focusable. Segments stay focusable for inspection.",
|
|
75
|
+
"type": "boolean",
|
|
76
|
+
"default": false
|
|
77
|
+
},
|
|
78
|
+
"step": {
|
|
79
|
+
"description": "Per-Arrow-keypress increment in seconds. 60 = minute precision (default), 900 = 15-minute, 1 = second precision.",
|
|
80
|
+
"type": "number",
|
|
81
|
+
"default": 60
|
|
82
|
+
},
|
|
83
|
+
"value": {
|
|
84
|
+
"description": "Current time value as ISO 8601 (\"HH:mm\" or \"HH:mm:ss\"). Empty when no value selected.",
|
|
85
|
+
"type": "string",
|
|
86
|
+
"default": ""
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"required": [
|
|
90
|
+
"component"
|
|
91
|
+
],
|
|
92
|
+
"unevaluatedProperties": false,
|
|
93
|
+
"x-adiaui": {
|
|
94
|
+
"anti_patterns": [
|
|
95
|
+
{
|
|
96
|
+
"fix": "{\"component\": \"TimePicker\", \"value\": \"09:30\"}\n",
|
|
97
|
+
"why": "Localized format is not a valid `value`. The contract requires ISO\n8601 time (`HH:mm` or `HH:mm:ss`, 24-hour). The display format is\nderived from `hourCycle` regardless of how the value is stored.\n",
|
|
98
|
+
"wrong": "{\"component\": \"TimePicker\", \"value\": \"9:30 AM\"}\n"
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"fix": "{\"component\": \"DatetimePicker\", \"value\": \"2026-05-24T09:30\"}\n",
|
|
102
|
+
"why": "Datetime string is invalid for TimePicker — the date portion is\nnot accepted. For datetime selection use the DatetimePicker\ncomponent.\n",
|
|
103
|
+
"wrong": "{\"component\": \"TimePicker\", \"value\": \"2026-05-24T09:30\"}\n"
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"fix": "{\"component\": \"TimePicker\", \"name\": \"field-name\"}\n",
|
|
107
|
+
"why": "Nesting a native time input violates ADR-0025 and bypasses\nElementInternals form participation.\n",
|
|
108
|
+
"wrong": "{\"component\": \"TimePicker\", \"children\": [\n {\"component\": \"Input\", \"type\": \"time\"}\n]}\n"
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"category": "input",
|
|
112
|
+
"composes": [],
|
|
113
|
+
"events": {
|
|
114
|
+
"change": {
|
|
115
|
+
"description": "Fired when the value commits (segment edit completes via Arrow / Tab / blur).",
|
|
116
|
+
"detail": {
|
|
117
|
+
"segment": {
|
|
118
|
+
"description": "Which segment commit fired the event (`hour` | `minute` | `second` | `meridiem`).",
|
|
119
|
+
"type": "string"
|
|
120
|
+
},
|
|
121
|
+
"value": {
|
|
122
|
+
"description": "Current value as ISO 8601 (\"HH:mm\" or \"HH:mm:ss\").",
|
|
123
|
+
"type": "string"
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"input": {
|
|
128
|
+
"description": "Fired on intermediate segment edits before commit.",
|
|
129
|
+
"detail": {
|
|
130
|
+
"value": {
|
|
131
|
+
"description": "In-flight value as ISO 8601.",
|
|
132
|
+
"type": "string"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
"invalid": {
|
|
137
|
+
"description": "Fired when a constraint is violated (min/max range, parse error).",
|
|
138
|
+
"detail": {
|
|
139
|
+
"reason": {
|
|
140
|
+
"description": "Why it failed (`min` | `max` | `parse`).",
|
|
141
|
+
"type": "string",
|
|
142
|
+
"enum": [
|
|
143
|
+
"min",
|
|
144
|
+
"max",
|
|
145
|
+
"parse"
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
"value": {
|
|
149
|
+
"description": "Value that failed validation.",
|
|
150
|
+
"type": "string"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
"examples": [
|
|
156
|
+
{
|
|
157
|
+
"description": "Time-of-day picker with 15-minute step and business-hours bounds.",
|
|
158
|
+
"a2ui": "[\n {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Start time\",\n \"children\": [\"t\"]},\n {\"id\": \"t\", \"component\": \"TimePicker\",\n \"name\": \"start-time\", \"value\": \"09:30\",\n \"min\": \"08:00\", \"max\": \"18:00\", \"step\": 900}\n]\n",
|
|
159
|
+
"name": "meeting-time-15min-step"
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"description": "Time picker with second precision for a log-cursor query.",
|
|
163
|
+
"a2ui": "[\n {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Cursor\",\n \"children\": [\"t\"]},\n {\"id\": \"t\", \"component\": \"TimePicker\",\n \"name\": \"cursor\", \"precision\": \"second\", \"step\": 1,\n \"value\": \"14:30:45\"}\n]\n",
|
|
164
|
+
"name": "log-cursor-second-precision"
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
"description": "Forced 12-hour cycle with AM/PM segment for an alarm picker.",
|
|
168
|
+
"a2ui": "[\n {\"id\": \"root\", \"component\": \"Field\", \"label\": \"Alarm\",\n \"children\": [\"t\"]},\n {\"id\": \"t\", \"component\": \"TimePicker\",\n \"name\": \"alarm\", \"hourCycle\": \"h12\", \"value\": \"07:00\"}\n]\n",
|
|
169
|
+
"name": "alarm-12h-cycle"
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"keywords": [
|
|
173
|
+
"time",
|
|
174
|
+
"timepicker",
|
|
175
|
+
"time-picker",
|
|
176
|
+
"clock",
|
|
177
|
+
"hour",
|
|
178
|
+
"minute",
|
|
179
|
+
"spinbutton"
|
|
180
|
+
],
|
|
181
|
+
"name": "UITimePicker",
|
|
182
|
+
"related": [
|
|
183
|
+
"CalendarPicker",
|
|
184
|
+
"Field",
|
|
185
|
+
"Input"
|
|
186
|
+
],
|
|
187
|
+
"slots": {
|
|
188
|
+
"prefix": {
|
|
189
|
+
"description": "Leading content (e.g. an `<icon-ui name=\"clock\">`); sits before the hour segment."
|
|
190
|
+
},
|
|
191
|
+
"suffix": {
|
|
192
|
+
"description": "Trailing content (e.g. a timezone label); sits after the last segment."
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
"states": [
|
|
196
|
+
{
|
|
197
|
+
"description": "Default, ready for interaction.",
|
|
198
|
+
"name": "idle"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"description": "One segment is the focus target.",
|
|
202
|
+
"attribute": "editing",
|
|
203
|
+
"name": "editing"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"description": "Non-interactive; dimmed.",
|
|
207
|
+
"attribute": "disabled",
|
|
208
|
+
"name": "disabled"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"description": "Keyboard focus ring on the host.",
|
|
212
|
+
"name": "focused",
|
|
213
|
+
"selector": ":focus-within"
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
"status": "stable",
|
|
217
|
+
"synonyms": {
|
|
218
|
+
"tags": [
|
|
219
|
+
"TimeInput",
|
|
220
|
+
"TimePicker"
|
|
221
|
+
],
|
|
222
|
+
"time": [
|
|
223
|
+
"clock",
|
|
224
|
+
"hour",
|
|
225
|
+
"minute",
|
|
226
|
+
"alarm"
|
|
227
|
+
]
|
|
228
|
+
},
|
|
229
|
+
"tag": "time-picker-ui",
|
|
230
|
+
"tokens": {
|
|
231
|
+
"--time-picker-bg": {
|
|
232
|
+
"description": "Host background color."
|
|
233
|
+
},
|
|
234
|
+
"--time-picker-border": {
|
|
235
|
+
"description": "Host border color."
|
|
236
|
+
},
|
|
237
|
+
"--time-picker-fg": {
|
|
238
|
+
"description": "Host text color."
|
|
239
|
+
},
|
|
240
|
+
"--time-picker-fg-muted": {
|
|
241
|
+
"description": "Muted text color (empty placeholder + separator)."
|
|
242
|
+
},
|
|
243
|
+
"--time-picker-px": {
|
|
244
|
+
"description": "Host inline padding."
|
|
245
|
+
},
|
|
246
|
+
"--time-picker-py": {
|
|
247
|
+
"description": "Host block padding."
|
|
248
|
+
},
|
|
249
|
+
"--time-picker-radius": {
|
|
250
|
+
"description": "Host border radius."
|
|
251
|
+
},
|
|
252
|
+
"--time-picker-segment-bg-focus": {
|
|
253
|
+
"description": "Focused segment background."
|
|
254
|
+
},
|
|
255
|
+
"--time-picker-segment-fg-focus": {
|
|
256
|
+
"description": "Focused segment text color."
|
|
257
|
+
},
|
|
258
|
+
"--time-picker-separator-fg": {
|
|
259
|
+
"description": "Separator (`:`) text color."
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
"traits": [
|
|
263
|
+
"focusable"
|
|
264
|
+
],
|
|
265
|
+
"version": 1
|
|
266
|
+
}
|
|
267
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
@scope (time-picker-ui) {
|
|
2
|
+
:where(:scope) {
|
|
3
|
+
/* ── Tokens ── */
|
|
4
|
+
--time-picker-bg-default: var(--a-ui-bg);
|
|
5
|
+
--time-picker-fg-default: var(--a-ui-text);
|
|
6
|
+
--time-picker-fg-muted-default: var(--a-ui-text-placeholder);
|
|
7
|
+
--time-picker-border-default: var(--a-ui-border);
|
|
8
|
+
--time-picker-border-hover-default: var(--a-ui-border-hover);
|
|
9
|
+
--time-picker-radius-default: var(--a-radius);
|
|
10
|
+
--time-picker-height-default: var(--a-size);
|
|
11
|
+
--time-picker-px-default: var(--a-ui-px);
|
|
12
|
+
--time-picker-py-default: 0;
|
|
13
|
+
--time-picker-gap-default: var(--a-space-1);
|
|
14
|
+
--time-picker-font-size-default: var(--a-ui-size);
|
|
15
|
+
|
|
16
|
+
--time-picker-segment-radius-default: var(--a-radius-sm);
|
|
17
|
+
--time-picker-segment-px-default: var(--a-space-1);
|
|
18
|
+
--time-picker-segment-bg-focus-default: var(--a-accent);
|
|
19
|
+
--time-picker-segment-fg-focus-default: var(--a-accent-fg);
|
|
20
|
+
|
|
21
|
+
--time-picker-separator-fg-default: var(--a-fg-muted);
|
|
22
|
+
|
|
23
|
+
--time-picker-focus-ring-default: var(--a-focus-ring);
|
|
24
|
+
--time-picker-focus-ring-invalid-default: var(--a-focus-ring-invalid);
|
|
25
|
+
|
|
26
|
+
--time-picker-duration-default: var(--a-duration-fast);
|
|
27
|
+
--time-picker-easing-default: var(--a-easing);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
:scope {
|
|
31
|
+
/* ── Base ── */
|
|
32
|
+
box-sizing: border-box;
|
|
33
|
+
display: inline-flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
gap: var(--time-picker-gap, var(--time-picker-gap-default));
|
|
36
|
+
min-height: var(--time-picker-height, var(--time-picker-height-default));
|
|
37
|
+
padding: var(--time-picker-py, var(--time-picker-py-default)) var(--time-picker-px, var(--time-picker-px-default));
|
|
38
|
+
background: var(--time-picker-bg, var(--time-picker-bg-default));
|
|
39
|
+
color: var(--time-picker-fg, var(--time-picker-fg-default));
|
|
40
|
+
border: 1px solid var(--time-picker-border, var(--time-picker-border-default));
|
|
41
|
+
border-radius: var(--time-picker-radius, var(--time-picker-radius-default));
|
|
42
|
+
font-family: inherit;
|
|
43
|
+
font-size: var(--time-picker-font-size, var(--time-picker-font-size-default));
|
|
44
|
+
font-variant-numeric: tabular-nums;
|
|
45
|
+
line-height: 1.4;
|
|
46
|
+
cursor: text;
|
|
47
|
+
transition:
|
|
48
|
+
border-color var(--time-picker-duration, var(--time-picker-duration-default)) var(--time-picker-easing, var(--time-picker-easing-default)),
|
|
49
|
+
background var(--time-picker-duration, var(--time-picker-duration-default)) var(--time-picker-easing, var(--time-picker-easing-default)),
|
|
50
|
+
box-shadow var(--time-picker-duration, var(--time-picker-duration-default)) var(--time-picker-easing, var(--time-picker-easing-default));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* ── Segments ── */
|
|
54
|
+
:scope [data-segment] {
|
|
55
|
+
display: inline-block;
|
|
56
|
+
min-width: 2ch;
|
|
57
|
+
padding: 0 var(--time-picker-segment-px, var(--time-picker-segment-px-default));
|
|
58
|
+
text-align: center;
|
|
59
|
+
border-radius: var(--time-picker-segment-radius, var(--time-picker-segment-radius-default));
|
|
60
|
+
color: inherit;
|
|
61
|
+
background: transparent;
|
|
62
|
+
outline: none;
|
|
63
|
+
caret-color: transparent;
|
|
64
|
+
cursor: text;
|
|
65
|
+
transition:
|
|
66
|
+
background var(--time-picker-duration, var(--time-picker-duration-default)) var(--time-picker-easing, var(--time-picker-easing-default)),
|
|
67
|
+
color var(--time-picker-duration, var(--time-picker-duration-default)) var(--time-picker-easing, var(--time-picker-easing-default));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Meridiem is a touch wider since it carries two letters (AM/PM). */
|
|
71
|
+
:scope [data-segment="meridiem"] {
|
|
72
|
+
min-width: 2.5ch;
|
|
73
|
+
text-transform: uppercase;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ── State: empty (placeholder via :empty) ── */
|
|
77
|
+
:scope [data-segment]:empty::before {
|
|
78
|
+
content: '--';
|
|
79
|
+
color: var(--time-picker-fg-muted, var(--time-picker-fg-muted-default));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* ── State: focused segment ── */
|
|
83
|
+
:scope [data-segment]:focus,
|
|
84
|
+
:scope [data-segment]:focus-visible {
|
|
85
|
+
background: var(--time-picker-segment-bg-focus, var(--time-picker-segment-bg-focus-default));
|
|
86
|
+
color: var(--time-picker-segment-fg-focus, var(--time-picker-segment-fg-focus-default));
|
|
87
|
+
outline: none;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* ── Separator ── */
|
|
91
|
+
:scope [data-separator] {
|
|
92
|
+
color: var(--time-picker-separator-fg, var(--time-picker-separator-fg-default));
|
|
93
|
+
pointer-events: none;
|
|
94
|
+
user-select: none;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* hover rules — outside @scope (matches input-ui's Safari 17.x workaround). */
|
|
99
|
+
time-picker-ui:not([disabled]):hover {
|
|
100
|
+
border-color: var(--time-picker-border-hover, var(--time-picker-border-hover-default));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* Focus ring on the host when any segment is focused.
|
|
104
|
+
Canonical L3 ring; consumed via --time-picker-focus-ring (aliases --a-focus-ring). */
|
|
105
|
+
time-picker-ui:not([disabled]):focus-within {
|
|
106
|
+
box-shadow: var(--time-picker-focus-ring, var(--time-picker-focus-ring-default));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
time-picker-ui[aria-invalid="true"]:not([disabled]):focus-within,
|
|
110
|
+
time-picker-ui[error]:not([disabled]):focus-within {
|
|
111
|
+
box-shadow: var(--time-picker-focus-ring-invalid, var(--time-picker-focus-ring-invalid-default));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Disabled / readonly affordance */
|
|
115
|
+
time-picker-ui[disabled] {
|
|
116
|
+
opacity: var(--a-opacity-disabled, 0.5);
|
|
117
|
+
pointer-events: none;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
time-picker-ui[readonly] [data-segment] {
|
|
121
|
+
cursor: default;
|
|
122
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<time-picker-ui>` — Time-of-day picker with discrete segments (hour, minute, optional second, optional AM/PM). Each segment follows the WAI-ARIA Spinbutton pattern with Arrow-key increment/decrement, Page Up/Down for larger jumps, Home/End for segment min/max, and Tab to move between segments. Form-associated input emitting ISO 8601 time string ("HH:mm" or "HH:mm:ss") via change events. Per ADR-0025 no native form controls — segments are contenteditable spans inside a custom host. SPEC-043.
|
|
3
|
+
*
|
|
4
|
+
* @see https://ui-kit.exe.xyz/site/components/time-picker
|
|
5
|
+
*
|
|
6
|
+
* Type declarations generated by scripts/build/dts-codegen.mjs from
|
|
7
|
+
* the component's `.a2ui.json` sidecar(s). Edit the source `.yaml`,
|
|
8
|
+
* run `npm run build:components`, then `npm run codegen:dts` to
|
|
9
|
+
* regenerate; or hand-author this file fully if rich event types are
|
|
10
|
+
* needed beyond what the yaml `events:` block can express.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { UIElement } from '../../core/element.js';
|
|
14
|
+
|
|
15
|
+
export interface TimePickerChangeEventDetail {
|
|
16
|
+
/** Which segment commit fired the event (`hour` | `minute` | `second` | `meridiem`). */
|
|
17
|
+
segment: string;
|
|
18
|
+
/** Current value as ISO 8601 ("HH:mm" or "HH:mm:ss"). */
|
|
19
|
+
value: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type TimePickerChangeEvent = CustomEvent<TimePickerChangeEventDetail>;
|
|
23
|
+
export interface TimePickerInputEventDetail {
|
|
24
|
+
/** In-flight value as ISO 8601. */
|
|
25
|
+
value: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type TimePickerInputEvent = CustomEvent<TimePickerInputEventDetail>;
|
|
29
|
+
export interface TimePickerInvalidEventDetail {
|
|
30
|
+
/** Why it failed (`min` | `max` | `parse`). */
|
|
31
|
+
reason: 'min' | 'max' | 'parse';
|
|
32
|
+
/** Value that failed validation. */
|
|
33
|
+
value: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type TimePickerInvalidEvent = CustomEvent<TimePickerInvalidEventDetail>;
|
|
37
|
+
|
|
38
|
+
export class UITimePicker extends UIElement {
|
|
39
|
+
/** Marks the field as required for form validation. Sets aria-required. */
|
|
40
|
+
required: boolean;
|
|
41
|
+
/** Disables interaction; dims the control */
|
|
42
|
+
disabled: boolean;
|
|
43
|
+
/** Hour cycle. Empty (default) derives from the document locale — most
|
|
44
|
+
en-* locales resolve to `h23`. `h12` forces a 12-hour cycle with an
|
|
45
|
+
AM/PM (meridiem) segment; `h23` forces 24-hour cycle.
|
|
46
|
+
*/
|
|
47
|
+
hourcycle: '' | 'h12' | 'h23';
|
|
48
|
+
/** BCP-47 locale tag used to derive hour-cycle when `hour-cycle` is empty. Falls back to `<html lang>` then to browser default. */
|
|
49
|
+
locale: string;
|
|
50
|
+
/** Latest selectable time as ISO 8601. Empty disables the constraint. */
|
|
51
|
+
max: string;
|
|
52
|
+
/** Earliest selectable time as ISO 8601. Empty disables the constraint. */
|
|
53
|
+
min: string;
|
|
54
|
+
/** Form field name for FormData submission */
|
|
55
|
+
name: string;
|
|
56
|
+
/** Per-segment placeholder text shown when a segment is empty. Defaults to "--". */
|
|
57
|
+
placeholder: string;
|
|
58
|
+
/** Whether the seconds segment is exposed. `minute` (default) hides seconds; `second` adds the seconds segment + separator. */
|
|
59
|
+
precision: 'minute' | 'second';
|
|
60
|
+
/** Prevents editing while keeping the field focusable. Segments stay focusable for inspection. */
|
|
61
|
+
readonly: boolean;
|
|
62
|
+
/** Per-Arrow-keypress increment in seconds. 60 = minute precision (default), 900 = 15-minute, 1 = second precision. */
|
|
63
|
+
step: number;
|
|
64
|
+
/** Current time value as ISO 8601 ("HH:mm" or "HH:mm:ss"). Empty when no value selected. */
|
|
65
|
+
value: string;
|
|
66
|
+
|
|
67
|
+
addEventListener<K extends keyof HTMLElementEventMap>(
|
|
68
|
+
type: K,
|
|
69
|
+
listener: (this: UITimePicker, ev: HTMLElementEventMap[K]) => unknown,
|
|
70
|
+
options?: boolean | AddEventListenerOptions,
|
|
71
|
+
): void;
|
|
72
|
+
addEventListener(type: 'change', listener: (ev: TimePickerChangeEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
73
|
+
addEventListener(type: 'input', listener: (ev: TimePickerInputEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
74
|
+
addEventListener(type: 'invalid', listener: (ev: TimePickerInvalidEvent) => unknown, options?: boolean | AddEventListenerOptions): void;
|
|
75
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# time-picker — Examples
|
|
2
|
+
|
|
3
|
+
## Default
|
|
4
|
+
|
|
5
|
+
```html
|
|
6
|
+
<time-picker-ui></time-picker-ui>
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## value
|
|
10
|
+
|
|
11
|
+
```html
|
|
12
|
+
<field-ui label="Start time">
|
|
13
|
+
<time-picker-ui value="09:30"></time-picker-ui>
|
|
14
|
+
</field-ui>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 15-minute step
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<field-ui label="Meeting">
|
|
21
|
+
<time-picker-ui value="09:30" step="900"></time-picker-ui>
|
|
22
|
+
</field-ui>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Second precision
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<time-picker-ui precision="second" step="1" value="14:30:45"></time-picker-ui>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## 12-hour cycle
|
|
32
|
+
|
|
33
|
+
```html
|
|
34
|
+
<time-picker-ui hour-cycle="h12" value="07:00"></time-picker-ui>
|
|
35
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<time-picker-ui>` — auto-registers the tag on import.
|
|
3
|
+
*
|
|
4
|
+
* For non-side-effect class import (test isolation, tag override), use
|
|
5
|
+
* the `class` subpath:
|
|
6
|
+
*
|
|
7
|
+
* import { UITimePicker } from '@adia-ai/web-components/components/time-picker/class';
|
|
8
|
+
*
|
|
9
|
+
* @see ../../USAGE.md#registration--auto-vs-explicit
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { defineIfFree } from '../../core/register.js';
|
|
13
|
+
import { UITimePicker } from './class.js';
|
|
14
|
+
|
|
15
|
+
defineIfFree('time-picker-ui', UITimePicker);
|
|
16
|
+
|
|
17
|
+
export { UITimePicker };
|