timepicker-ui-mcp 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 pglejzer (Piotr Glejzer)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,111 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # timepicker-ui MCP server
2
+
3
+ An MCP server for `timepicker-ui`. Connect it to Claude Code, Claude Desktop or another MCP client and the model can look up options, events and themes, generate setup snippets and custom themes, and migrate v3 code. Everything it returns comes from the library source, not from the model's memory.
4
+
5
+ It runs over stdio and needs Node 18 or newer.
6
+
7
+ ## Tools
8
+
9
+ | Tool | Description |
10
+ |------|-------------|
11
+ | `list_themes` | Built-in themes and their CSS import paths. |
12
+ | `list_modes` | UI modes (`clock`, `wheel`, `compact-wheel`) and the plugin each needs. |
13
+ | `list_plugins` | Optional plugins (range, timezone, wheel) with import paths. |
14
+ | `list_events` | Every EventEmitter event with its payload fields. |
15
+ | `list_api` | Public instance and static API, plus the `getValue`/`setValue` contract. |
16
+ | `list_css_classes` | The `tp-ui-` class names rendered by the templates. |
17
+ | `get_options` | Grouped options with type, default and description. Optional `group` filter. |
18
+ | `explain_option` | Full detail for one option (`group` + `name`). |
19
+ | `get_theme` | The `--tp-` variables a built-in theme overrides. |
20
+ | `framework_recipe` | Integration recipe and SSR notes for vanilla, react, next, vue, angular, svelte. |
21
+ | `migration_guide` | `v3->v4` field mapping, or the `v4.3->v4.4` / `v4.4->v4.5` changes. |
22
+ | `generate_snippet` | Vanilla JS or React setup (CSS imports and plugin registration). |
23
+ | `generate_custom_theme` | A `[data-theme]` CSS block from `overrides`, or a full scaffold. |
24
+ | `validate_time` | Checks `HH:MM`, `HH:MM:SS`, `h:MM AM/PM` or `h:MM:SS AM/PM` against a 12h or 24h clock. |
25
+ | `validate_disabled_time` | Checks a `clock.disabledTime` config (hours, minutes, seconds, range strings). |
26
+
27
+ ## Resources
28
+
29
+ | URI | Description |
30
+ |-----|-------------|
31
+ | `timepicker-ui://reference` | Grouped-options summary. |
32
+ | `timepicker-ui://css-variables` | Every `--tp-` variable and its default. |
33
+ | `timepicker-ui://custom-theme-guide` | How to author a custom theme. |
34
+ | `timepicker-ui://troubleshooting` | Common symptoms, causes and fixes. |
35
+
36
+ ## Prompts
37
+
38
+ | Prompt | Argument | Purpose |
39
+ |--------|----------|---------|
40
+ | `integrate` | `framework` | Walk through a framework integration. |
41
+ | `build-custom-theme` | `description` | Turn a palette into a theme. |
42
+ | `migrate-v3-to-v4` | `code` | Convert v3 code to v4 grouped options. |
43
+
44
+ ## Build and test
45
+
46
+ ```bash
47
+ cd mcp-server
48
+ npm install
49
+ npm run build # generate data, compile, copy generated JSON into build/
50
+ npm test # start the server and check that tools, resources and prompts respond
51
+ npm run inspect # open the MCP Inspector against the built server
52
+ ```
53
+
54
+ ## Where the data comes from
55
+
56
+ `npm run build` first runs `scripts/generate.mjs`. It reads the library source in `../app` and writes `src/generated/*.json`: options and event payloads from `options.d.ts` and `types.d.ts`, the EventEmitter map, the theme stylesheets and `variables.scss`, and the `tp-ui-` classes from the templates.
57
+
58
+ The generated JSON is committed, so the server works without the `app/` source next to it. After changing the library, run `npm run build` again to refresh it.
59
+
60
+ ## Adding it to Claude Code
61
+
62
+ Build it first. No API keys or env vars are needed. `--scope user` makes it available in every project; leave it out to register it for the current project only. Check it with `claude mcp list`, which should show `timepicker-ui ✓ Connected`.
63
+
64
+ Point at the built file directly:
65
+
66
+ ```bash
67
+ claude mcp add --scope user timepicker-ui -- node /absolute/path/to/timepicker-ui/mcp-server/build/index.js
68
+ ```
69
+
70
+ Or link the bin once with `npm link` (or `npm install -g .`) and skip the path:
71
+
72
+ ```bash
73
+ npm link
74
+ claude mcp add --scope user timepicker-ui -- timepicker-ui-mcp
75
+ ```
76
+
77
+ The package isn't on npm yet. Once it is, this will work without cloning anything:
78
+
79
+ ```bash
80
+ claude mcp add --scope user timepicker-ui -- npx -y timepicker-ui-mcp
81
+ ```
82
+
83
+ If you work in this repo, you can also add a project `.mcp.json` (after `npm install && npm run build` in `mcp-server/`):
84
+
85
+ ```json
86
+ {
87
+ "mcpServers": {
88
+ "timepicker-ui": {
89
+ "command": "node",
90
+ "args": ["mcp-server/build/index.js"]
91
+ }
92
+ }
93
+ }
94
+ ```
95
+
96
+ ## Adding it to Claude Desktop
97
+
98
+ Edit `claude_desktop_config.json`. It's in `%APPDATA%\Claude\` on Windows and `~/Library/Application Support/Claude/` on macOS.
99
+
100
+ ```json
101
+ {
102
+ "mcpServers": {
103
+ "timepicker-ui": {
104
+ "command": "node",
105
+ "args": ["/absolute/path/to/timepicker-ui/mcp-server/build/index.js"]
106
+ }
107
+ }
108
+ }
109
+ ```
110
+
111
+ Restart Claude Desktop after saving.
@@ -0,0 +1,281 @@
1
+ export const FRAMEWORK_NAMES = ['vanilla', 'react', 'next', 'vue', 'angular', 'svelte'];
2
+ export const FRAMEWORK_RECIPES = {
3
+ vanilla: {
4
+ title: 'Vanilla JS / TS',
5
+ notes: [
6
+ 'Call create() once the input exists in the DOM.',
7
+ 'Call destroy() when you remove the input to release listeners and the modal.',
8
+ ],
9
+ code: [
10
+ "import { TimepickerUI } from 'timepicker-ui';",
11
+ "import 'timepicker-ui/main.css';",
12
+ '',
13
+ "const input = document.querySelector('#time');",
14
+ 'const picker = new TimepickerUI(input, { clock: { type: \'24h\' } });',
15
+ 'picker.create();',
16
+ ].join('\n'),
17
+ },
18
+ react: {
19
+ title: 'React',
20
+ notes: [
21
+ 'Construct in an effect after mount; destroy in the cleanup. Never construct during render.',
22
+ 'Empty dependency array so it initializes once. Read values via picker.getValue() or the events.',
23
+ 'There is also an official wrapper: the `timepicker-ui-react` package.',
24
+ ],
25
+ code: [
26
+ "import { useEffect, useRef } from 'react';",
27
+ "import { TimepickerUI } from 'timepicker-ui';",
28
+ "import 'timepicker-ui/main.css';",
29
+ '',
30
+ 'export function TimePicker() {',
31
+ ' const ref = useRef<HTMLInputElement>(null);',
32
+ ' useEffect(() => {',
33
+ ' if (!ref.current) return;',
34
+ ' const picker = new TimepickerUI(ref.current, { clock: { type: \'24h\' } });',
35
+ ' picker.create();',
36
+ " picker.on('confirm', (d) => console.log(d.hour, d.minutes));",
37
+ ' return () => picker.destroy();',
38
+ ' }, []);',
39
+ ' return <input ref={ref} />;',
40
+ '}',
41
+ ].join('\n'),
42
+ },
43
+ next: {
44
+ title: 'Next.js (App Router)',
45
+ notes: [
46
+ 'The component must be a Client Component — add "use client" at the top.',
47
+ 'timepicker-ui touches the DOM, so keep all usage inside useEffect (runs only in the browser). The library is SSR-safe (no DOM access at import time), but you still must not call create() on the server.',
48
+ 'If you ever see hydration/DOM errors, dynamic-import the picker component with { ssr: false }.',
49
+ ],
50
+ code: [
51
+ "'use client';",
52
+ "import { useEffect, useRef } from 'react';",
53
+ "import { TimepickerUI } from 'timepicker-ui';",
54
+ "import 'timepicker-ui/main.css';",
55
+ '',
56
+ 'export function TimePicker() {',
57
+ ' const ref = useRef<HTMLInputElement>(null);',
58
+ ' useEffect(() => {',
59
+ ' if (!ref.current) return;',
60
+ ' const picker = new TimepickerUI(ref.current);',
61
+ ' picker.create();',
62
+ ' return () => picker.destroy();',
63
+ ' }, []);',
64
+ ' return <input ref={ref} />;',
65
+ '}',
66
+ ].join('\n'),
67
+ },
68
+ vue: {
69
+ title: 'Vue 3',
70
+ notes: [
71
+ 'Create in onMounted, destroy in onBeforeUnmount.',
72
+ 'Use a template ref to the input element.',
73
+ ],
74
+ code: [
75
+ '<script setup lang="ts">',
76
+ "import { ref, onMounted, onBeforeUnmount } from 'vue';",
77
+ "import { TimepickerUI } from 'timepicker-ui';",
78
+ "import 'timepicker-ui/main.css';",
79
+ '',
80
+ 'const el = ref<HTMLInputElement | null>(null);',
81
+ 'let picker: TimepickerUI | null = null;',
82
+ 'onMounted(() => {',
83
+ ' if (!el.value) return;',
84
+ ' picker = new TimepickerUI(el.value, { clock: { type: \'24h\' } });',
85
+ ' picker.create();',
86
+ '});',
87
+ 'onBeforeUnmount(() => picker?.destroy());',
88
+ '</script>',
89
+ '',
90
+ '<template>',
91
+ ' <input ref="el" />',
92
+ '</template>',
93
+ ].join('\n'),
94
+ },
95
+ angular: {
96
+ title: 'Angular',
97
+ notes: [
98
+ 'Create in ngAfterViewInit (the view/input exists), destroy in ngOnDestroy.',
99
+ 'Add timepicker-ui/main.css to angular.json styles or import it in styles.css.',
100
+ 'Use ViewChild + ElementRef to reach the input.',
101
+ ],
102
+ code: [
103
+ "import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core';",
104
+ "import { TimepickerUI } from 'timepicker-ui';",
105
+ '',
106
+ '@Component({',
107
+ " selector: 'app-time',",
108
+ " template: '<input #time />',",
109
+ '})',
110
+ 'export class TimeComponent implements AfterViewInit, OnDestroy {',
111
+ " @ViewChild('time') input!: ElementRef<HTMLInputElement>;",
112
+ ' private picker?: TimepickerUI;',
113
+ ' ngAfterViewInit() {',
114
+ ' this.picker = new TimepickerUI(this.input.nativeElement, { clock: { type: \'24h\' } });',
115
+ ' this.picker.create();',
116
+ ' }',
117
+ ' ngOnDestroy() {',
118
+ ' this.picker?.destroy();',
119
+ ' }',
120
+ '}',
121
+ ].join('\n'),
122
+ },
123
+ svelte: {
124
+ title: 'Svelte',
125
+ notes: [
126
+ 'Bind the input, create in onMount, destroy in the returned cleanup.',
127
+ ],
128
+ code: [
129
+ '<script lang="ts">',
130
+ " import { onMount } from 'svelte';",
131
+ " import { TimepickerUI } from 'timepicker-ui';",
132
+ " import 'timepicker-ui/main.css';",
133
+ '',
134
+ ' let input: HTMLInputElement;',
135
+ ' onMount(() => {',
136
+ ' const picker = new TimepickerUI(input, { clock: { type: \'24h\' } });',
137
+ ' picker.create();',
138
+ ' return () => picker.destroy();',
139
+ ' });',
140
+ '</script>',
141
+ '',
142
+ '<input bind:this={input} />',
143
+ ].join('\n'),
144
+ },
145
+ };
146
+ export const MIGRATION_V3_TO_V4 = {
147
+ summary: [
148
+ 'v4 replaced the flat options object (40+ fields) with grouped options. There is NO backward-compatibility layer — all v3 code must be updated.',
149
+ 'Event handling also moved to the EventEmitter API (picker.on(event, handler)) and the grouped callbacks.* options.',
150
+ ],
151
+ mappings: [
152
+ {
153
+ group: 'clock',
154
+ rows: [
155
+ { from: 'clockType', to: 'clock.type' },
156
+ { from: 'incrementHours', to: 'clock.incrementHours' },
157
+ { from: 'incrementMinutes', to: 'clock.incrementMinutes' },
158
+ { from: 'autoSwitchToMinutes', to: 'clock.autoSwitchToMinutes' },
159
+ { from: 'disabledTime', to: 'clock.disabledTime' },
160
+ { from: 'currentTime', to: 'clock.defaultTime' },
161
+ ],
162
+ },
163
+ {
164
+ group: 'ui',
165
+ rows: [
166
+ { from: 'theme', to: 'ui.theme' },
167
+ { from: 'animation', to: 'ui.animation' },
168
+ { from: 'backdrop', to: 'ui.backdrop' },
169
+ { from: 'mobile', to: 'ui.initialView' },
170
+ { from: 'enableSwitchIcon', to: 'ui.viewSwitch' },
171
+ { from: 'editable', to: 'ui.editable' },
172
+ { from: 'enableScrollbar', to: 'ui.allowPageScroll' },
173
+ { from: 'cssClass', to: 'ui.cssClass' },
174
+ { from: 'appendModalSelector', to: 'ui.appendTo' },
175
+ { from: 'iconTemplate', to: 'ui.keyboardIcon' },
176
+ { from: 'iconTemplateMobile', to: 'ui.clockIcon' },
177
+ { from: 'inline', to: 'ui.inline' },
178
+ ],
179
+ },
180
+ {
181
+ group: 'labels',
182
+ rows: [
183
+ { from: 'amLabel', to: 'labels.am' },
184
+ { from: 'pmLabel', to: 'labels.pm' },
185
+ { from: 'okLabel', to: 'labels.ok' },
186
+ { from: 'cancelLabel', to: 'labels.cancel' },
187
+ { from: 'timeLabel', to: 'labels.clockTitle' },
188
+ { from: 'mobileTimeLabel', to: 'labels.keyboardTitle' },
189
+ { from: 'hourMobileLabel', to: 'labels.hour' },
190
+ { from: 'minuteMobileLabel', to: 'labels.minute' },
191
+ ],
192
+ },
193
+ {
194
+ group: 'behavior',
195
+ rows: [
196
+ { from: 'focusInputAfterCloseModal', to: 'behavior.returnFocus' },
197
+ { from: 'focusTrap', to: 'behavior.focusTrap' },
198
+ { from: 'delayHandler', to: 'behavior.delayHandler' },
199
+ { from: 'id', to: 'behavior.id' },
200
+ ],
201
+ },
202
+ {
203
+ group: 'callbacks',
204
+ rows: [
205
+ { from: 'onOpen', to: 'callbacks.onOpen' },
206
+ { from: 'onCancel', to: 'callbacks.onCancel' },
207
+ { from: 'onConfirm', to: 'callbacks.onConfirm' },
208
+ { from: 'onUpdate', to: 'callbacks.onUpdate' },
209
+ { from: 'onSelectHour', to: 'callbacks.onSelectHour' },
210
+ { from: 'onSelectMinute', to: 'callbacks.onSelectMinute' },
211
+ { from: 'onSelectAM', to: 'callbacks.onSelectAM' },
212
+ { from: 'onSelectPM', to: 'callbacks.onSelectPM' },
213
+ { from: 'onError', to: 'callbacks.onError' },
214
+ ],
215
+ },
216
+ ],
217
+ notes: [
218
+ 'Reading options also changed: options.clockType -> options.clock.type, options.amLabel -> options.labels.am.',
219
+ 'setOptions() takes grouped options too: setOptions({ clock: { type: "24h" } }).',
220
+ 'Some values changed shape: mobile: true becomes ui.initialView: "keyboard", currentTime: true becomes clock.defaultTime: "now".',
221
+ 'CSS class names were renamed in v4 (tp-ui- prefix). Re-check any custom CSS selectors.',
222
+ ],
223
+ };
224
+ export const MIGRATION_V43_TO_V44 = [
225
+ 'Non-breaking. Adds the blueprint and blueprint-dark themes.',
226
+ 'Adds 16 localizable accessibility labels under labels.* (e.g. hourLabel, minuteLabel, announceHour).',
227
+ 'Adds Home/End/PageUp/PageDown keyboard navigation. No migration needed.',
228
+ ];
229
+ export const MIGRATION_V44_TO_V45 = [
230
+ 'Non-breaking. With clock.showSeconds off (the default) values, getValue() and event payloads are the same as in 4.4.',
231
+ 'Optional seconds: clock.showSeconds, clock.incrementSeconds (1, 5, 10, 15, 20 or 30), clock.autoSwitchToSeconds and clock.disabledTime.seconds. Values become HH:MM:SS or HH:MM:SS AM/PM.',
232
+ 'New label labels.second; new event select:second and callbacks.onSelectSecond; seconds on open, confirm and update; durationSeconds on range:confirm and range:validation.',
233
+ 'Range edges in clock.disabledTime.ranges may carry seconds. An edge without seconds covers its whole minute, so 4.4 ranges disable the same minutes.',
234
+ 'setOptions() (and update()) with an invalid disabledTime reports it through the error event and keeps the previous options instead of throwing.',
235
+ 'behavior.returnFocus (formerly focusInputAfterClose) still defaults to false; 5.0 makes true the default, so set it to true now.',
236
+ 'Renamed options; the old names still work and are removed in 5.0: ui.mobile -> ui.initialView, ui.enableSwitchIcon -> ui.viewSwitch, ui.enableScrollbar -> ui.allowPageScroll, ui.appendModalSelector -> ui.appendTo, ui.iconTemplate / iconTemplateMobile -> ui.keyboardIcon / clockIcon, ui.inline.containerId -> ui.inline.container, clock.currentTime -> clock.defaultTime, clock.smoothHourSnap -> clock.discreteHourJump (inverted), clock.disabledTime.interval -> ranges, behavior.focusInputAfterClose -> returnFocus, timezone.whitelist -> list, clearBehavior.clearInput -> ui.clearButton: { clearInput }. Labels: one key per unit (labels.hour, labels.minute, labels.second), labels.clockTitle / keyboardTitle, labels.clock / period / timeFields / range / switchToKeyboard / switchToClock, and range.fromLabel / toLabel / timezone.label move to labels.rangeFrom / rangeTo / timezone.',
237
+ 'New: setOptions(), select:period with onSelectPeriod, switch:face with onSwitchFace, clock.type: "auto" (12h or 24h from the browser locale); ui.appendTo and ui.inline.container also accept an element.',
238
+ 'The focus ring is a single 3px ring in --tp-focus-ring; --tp-focus-ring-halo was removed.',
239
+ 'Deprecated (removed in 5.0): OptionTypes (use TimepickerOptions), labels.timezoneSelectorLabel, labels.format24Label, labels.toggleLabel, clock.currentTime.locales, getValue().degreesHours / degreesMinutes, the hide event, update() (use setOptions()), select:am / select:pm with onSelectAM / onSelectPM (use select:period / onSelectPeriod) and the renamed option names.',
240
+ ];
241
+ export const TROUBLESHOOTING = [
242
+ {
243
+ symptom: 'Picker opens but is completely unstyled.',
244
+ cause: "The core stylesheet was not imported.",
245
+ fix: "Always import 'timepicker-ui/main.css'. For a non-basic theme also import 'timepicker-ui/theme-<name>.css'.",
246
+ },
247
+ {
248
+ symptom: "An 'error' event fires / a feature option is ignored.",
249
+ cause: 'A plugin (range, timezone, wheel) was used without being registered.',
250
+ fix: "Import the plugin and call PluginRegistry.register(Plugin) once at startup before creating the picker.",
251
+ },
252
+ {
253
+ symptom: 'Wheel / compact-wheel mode renders as a normal clock.',
254
+ cause: 'The wheel plugin is required for those modes.',
255
+ fix: "Register WheelPlugin from 'timepicker-ui/plugins/wheel' and set ui.mode to 'wheel' or 'compact-wheel'.",
256
+ },
257
+ {
258
+ symptom: 'Modal appears in the wrong place or behind other UI.',
259
+ cause: 'It is appended to <body> by default.',
260
+ fix: "Set ui.appendTo to a container selector or element, or check stacking context / z-index of ancestors.",
261
+ },
262
+ {
263
+ symptom: 'Setting ui.theme to a custom name does nothing.',
264
+ cause: 'The theme CSS was not loaded, or the data-theme name does not match.',
265
+ fix: "Author [data-theme='name'] { --tp-*: ... }, import it after main.css, and pass ui.theme = 'name'.",
266
+ },
267
+ {
268
+ symptom: 'Listeners or modal linger after the input is removed (e.g. SPA route change).',
269
+ cause: 'The instance was not destroyed.',
270
+ fix: 'Call picker.destroy() in your framework cleanup hook (useEffect cleanup, onBeforeUnmount, ngOnDestroy).',
271
+ },
272
+ {
273
+ symptom: 'TypeScript complains about a custom theme name.',
274
+ cause: 'ui.theme is a union of built-in theme names.',
275
+ fix: "Cast the custom name: ui: { theme: 'ocean' as any }.",
276
+ },
277
+ ];
278
+ export const IO_CONTRACT = {
279
+ getValue: 'getValue() returns { hour: string; minutes: string; type?: string; time: string; degreesHours: number | null; degreesMinutes: number | null }.',
280
+ setValue: 'setValue(time, updateInput?) accepts "HH:MM" (24h) or "h:MM AM/PM" (12h), e.g. "14:30" or "2:30 PM". updateInput defaults to writing the input value.',
281
+ };
package/build/data.js ADDED
@@ -0,0 +1,81 @@
1
+ export const PACKAGE_VERSION = '4.5';
2
+ export const THEMES = [
3
+ { name: 'basic', cssImport: 'timepicker-ui/main.css', note: 'default theme, bundled in main.css' },
4
+ { name: 'ai', cssImport: 'timepicker-ui/theme-ai.css' },
5
+ { name: 'blueprint', cssImport: 'timepicker-ui/theme-blueprint.css', note: 'added in v4.4' },
6
+ { name: 'blueprint-dark', cssImport: 'timepicker-ui/theme-blueprint-dark.css', note: 'added in v4.4' },
7
+ { name: 'crane', cssImport: 'timepicker-ui/theme-crane.css' },
8
+ { name: 'crane-straight', cssImport: 'timepicker-ui/theme-crane-straight.css' },
9
+ { name: 'cyberpunk', cssImport: 'timepicker-ui/theme-cyberpunk.css' },
10
+ { name: 'dark', cssImport: 'timepicker-ui/theme-dark.css' },
11
+ { name: 'glassmorphic', cssImport: 'timepicker-ui/theme-glassmorphic.css' },
12
+ { name: 'm2', cssImport: 'timepicker-ui/theme-m2.css' },
13
+ { name: 'm3-green', cssImport: 'timepicker-ui/theme-m3-green.css' },
14
+ { name: 'pastel', cssImport: 'timepicker-ui/theme-pastel.css' },
15
+ ];
16
+ export const THEME_NAMES = THEMES.map((t) => t.name);
17
+ export const MODES = [
18
+ { name: 'clock', description: 'Analog clock face with draggable hands (default).' },
19
+ {
20
+ name: 'wheel',
21
+ description: 'Scrollable wheel picker for hours/minutes.',
22
+ requiresPlugin: 'wheel',
23
+ },
24
+ {
25
+ name: 'compact-wheel',
26
+ description: 'Condensed inline wheel variant.',
27
+ requiresPlugin: 'wheel',
28
+ },
29
+ ];
30
+ export const MODE_NAMES = MODES.map((m) => m.name);
31
+ export const PLUGINS = [
32
+ {
33
+ name: 'range',
34
+ export: 'RangePlugin',
35
+ importPath: 'timepicker-ui/plugins/range',
36
+ description: 'Start/end time selection with a tab UI.',
37
+ enableOption: 'range: { enabled: true }',
38
+ },
39
+ {
40
+ name: 'timezone',
41
+ export: 'TimezonePlugin',
42
+ importPath: 'timepicker-ui/plugins/timezone',
43
+ description: 'Timezone dropdown with keyboard navigation.',
44
+ enableOption: "timezone: { enabled: true, default: 'Europe/Warsaw' }",
45
+ },
46
+ {
47
+ name: 'wheel',
48
+ export: 'WheelPlugin',
49
+ importPath: 'timepicker-ui/plugins/wheel',
50
+ description: 'Enables the wheel / compact-wheel UI modes, drag and momentum.',
51
+ enableOption: "ui: { mode: 'wheel' }",
52
+ },
53
+ ];
54
+ export const PLUGIN_NAMES = PLUGINS.map((p) => p.name);
55
+ export const API_METHODS = [
56
+ { signature: 'new TimepickerUI(selectorOrElement, options?)', description: 'Construct an instance.' },
57
+ { signature: 'create()', description: 'Initialize and render the picker.' },
58
+ { signature: 'open(callback?)', description: 'Open the modal.' },
59
+ { signature: 'close(update?, callback?)', description: 'Close the modal.' },
60
+ {
61
+ signature: 'destroy(options?)',
62
+ description: 'Clean up DOM and listeners. options: { keepInputValue?, callback? }.',
63
+ },
64
+ {
65
+ signature: 'getValue()',
66
+ description: 'Returns { hour, minutes, type?, time, degreesHours, degreesMinutes }.',
67
+ },
68
+ { signature: 'setValue(time, updateInput?)', description: 'Set time, e.g. "14:30" or "2:30 PM".' },
69
+ { signature: 'setOptions(options)', description: 'Change options at runtime; groups you leave out keep their values.' },
70
+ {
71
+ signature: 'update({ options, create? }, callback?)',
72
+ description: 'Deprecated, use setOptions(). Removed in 5.0.',
73
+ },
74
+ { signature: 'on(event, handler)', description: 'Subscribe to an event.' },
75
+ { signature: 'once(event, handler)', description: 'Subscribe once.' },
76
+ { signature: 'off(event, handler?)', description: 'Unsubscribe.' },
77
+ { signature: 'TimepickerUI.getById(id)', description: 'Get an instance by custom behavior.id.', static: true },
78
+ { signature: 'TimepickerUI.getAllInstances()', description: 'All live instances.', static: true },
79
+ { signature: 'TimepickerUI.isAvailable(selector)', description: 'Check the element exists.', static: true },
80
+ { signature: 'TimepickerUI.destroyAll()', description: 'Destroy every instance.', static: true },
81
+ ];
@@ -0,0 +1,67 @@
1
+ [
2
+ "tp-ui-am",
3
+ "tp-ui-body",
4
+ "tp-ui-cancel-btn",
5
+ "tp-ui-circle-hand",
6
+ "tp-ui-clear-btn",
7
+ "tp-ui-clock-face",
8
+ "tp-ui-clock-hand",
9
+ "tp-ui-compact-wheel-mode",
10
+ "tp-ui-dot",
11
+ "tp-ui-dots",
12
+ "tp-ui-footer",
13
+ "tp-ui-has-seconds",
14
+ "tp-ui-header",
15
+ "tp-ui-hour",
16
+ "tp-ui-hour-text",
17
+ "tp-ui-input-ripple-wrapper",
18
+ "tp-ui-input-wrapper",
19
+ "tp-ui-keyboard-icon",
20
+ "tp-ui-keyboard-icon-wrapper",
21
+ "tp-ui-label-",
22
+ "tp-ui-minute-text",
23
+ "tp-ui-minutes",
24
+ "tp-ui-mobile-clock-wrapper",
25
+ "tp-ui-modal",
26
+ "tp-ui-ok-btn",
27
+ "tp-ui-pm",
28
+ "tp-ui-range-from",
29
+ "tp-ui-range-from-time",
30
+ "tp-ui-range-header",
31
+ "tp-ui-range-mode",
32
+ "tp-ui-range-tab",
33
+ "tp-ui-range-tab-label",
34
+ "tp-ui-range-tab-value",
35
+ "tp-ui-range-to",
36
+ "tp-ui-range-to-time",
37
+ "tp-ui-second-text",
38
+ "tp-ui-seconds",
39
+ "tp-ui-select-time",
40
+ "tp-ui-timezone",
41
+ "tp-ui-timezone-arrow",
42
+ "tp-ui-timezone-dropdown",
43
+ "tp-ui-timezone-label",
44
+ "tp-ui-timezone-menu",
45
+ "tp-ui-timezone-selected",
46
+ "tp-ui-tips-wrapper",
47
+ "tp-ui-tips-wrapper-24h",
48
+ "tp-ui-type-mode",
49
+ "tp-ui-tz-mode",
50
+ "tp-ui-wheel-ampm",
51
+ "tp-ui-wheel-column",
52
+ "tp-ui-wheel-column-wrapper",
53
+ "tp-ui-wheel-container",
54
+ "tp-ui-wheel-highlight",
55
+ "tp-ui-wheel-hours",
56
+ "tp-ui-wheel-item",
57
+ "tp-ui-wheel-minutes",
58
+ "tp-ui-wheel-mode",
59
+ "tp-ui-wheel-padding",
60
+ "tp-ui-wheel-seconds",
61
+ "tp-ui-wheel-separator",
62
+ "tp-ui-wrapper",
63
+ "tp-ui-wrapper-btn",
64
+ "tp-ui-wrapper-time",
65
+ "tp-ui-wrapper-time-24h",
66
+ "tp-ui-wrapper-type-time"
67
+ ]