@neuronection/assistant-ui 0.8.0 → 0.8.1

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 CHANGED
@@ -1,5 +1,16 @@
1
1
  # @neuronection/assistant-ui
2
2
 
3
+ ## 0.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`0421e0e`](https://github.com/neuronection/assistant-ui/commit/0421e0e02ed994182ac3d2e79c23f786aff87b36) Thanks [@constLiakos](https://github.com/constLiakos)! - README: family showcase — neuronection.com, the three Assistant apps
8
+ (career / study / health-assistant.io) front and center; complete component
9
+ index incl. PanelModal, Textarea and the dark-mode / z-token theming notes.
10
+ Docs: correct CSS import order in theming.md, TW3 translate-collision +
11
+ z-index notes in adoption.md, positioning/z-index/audit-import rules in
12
+ adding-a-component.md, AGENTS.md gotchas updated.
13
+
3
14
  ## 0.8.0
4
15
 
5
16
  ### Minor Changes
package/README.md CHANGED
@@ -1,14 +1,25 @@
1
1
  # assistant-ui
2
2
 
3
- Shared React component library for the **Assistant family** of apps
4
- ([career-assistant](https://github.com/neuronection/career-assistant),
5
- [study-assistant](https://github.com/neuronection/study-assistant),
6
- [health-assistant](https://github.com/health-assistant-io/health-assistant)).
3
+ Shared React component library for the **Assistant family** three sibling
4
+ apps that AI-help people with career, study, and health. One package, three
5
+ apps: family look by default, app flavor via CSS-variable design tokens.
6
+ Works in React 18 & 19 and alongside Tailwind 3 or 4 — the library ships
7
+ **precompiled CSS**, so your app's Tailwind never compiles library classes.
7
8
 
8
- One package, three apps: family look by default, app flavor via CSS-variable
9
- design tokens. Works in React 18 & 19 and alongside Tailwind 3 or 4 — the
10
- library ships **precompiled CSS**, so your app's Tailwind never compiles
11
- library classes.
9
+ **[neuronection.com](https://neuronection.com)** the family hub.
10
+
11
+ | App | What it is |
12
+ |---|---|
13
+ | [**career-assistant**](https://github.com/neuronection/career-assistant) | Job discovery, AI matching and university pathways for students |
14
+ | [**study-assistant**](https://github.com/neuronection/study-assistant) | Study workspace: notes, materials, chat with math & code rendering |
15
+ | [**health-assistant**](https://health-assistant.io) | Universal health data platform — self-hosted, privacy-first, [open source](https://github.com/health-assistant-io/health-assistant) |
16
+
17
+ The family shares its UI DNA here: **40+ modules, 260+ tests** (keyboard-nav
18
+ + axe per component), built on Radix, token-themed so every app looks like a
19
+ sibling without sharing a stack. Patterns the apps actually use — provider &
20
+ model settings blocks, AI affordances (ask/fill/act), date & clock pickers,
21
+ async comboboxes, file attachment surfaces — live in the package, not
22
+ copy-pasted in three repos.
12
23
 
13
24
  ## Install
14
25
 
@@ -30,8 +41,8 @@ import { Button, ConfirmationModal, Input } from '@neuronection/assistant-ui'
30
41
  ## Theming
31
42
 
32
43
  All visuals flow through `--as-*` CSS variables. The defaults are the family
33
- look (extracted from study-assistant); each app overrides identity tokens in a
34
- small `theme.css`:
44
+ look (extracted from study-assistant); each app overrides identity tokens in
45
+ a small `theme.css`:
35
46
 
36
47
  ```css
37
48
  :root {
@@ -40,28 +51,10 @@ small `theme.css`:
40
51
  }
41
52
  ```
42
53
 
43
- See [`themes/`](./themes) for per-app starting points and
44
- `ThemeScope` for scoping tokens to a subtree. Override **tokens**, not
45
- internal class names class names are not API.
46
-
47
- ## Peer requirements
48
-
49
- | Package | Range |
50
- |---|---|
51
- | react / react-dom | `>=18 <20` |
52
- | lucide-react | `>=0.460 <2` |
53
-
54
- Tailwind is **not** required — but if your app uses Tailwind 3 or 4, both work
55
- without configuration. Do **not** add this package to your Tailwind
56
- `content`/`@source`.
57
-
58
- ## Documentation
59
-
60
- - [Local development](./docs/local-development.md) — live-test library changes in the family apps without publishing
61
- - [Adopting in an app](./docs/adoption.md) — the install/switchover recipe each family app follows
62
- - [Theming](./docs/theming.md) — tokens, app themes, styling hooks
63
- - [Publishing](./docs/publishing.md) — the Changesets release flow and CI setup
64
- - [Adding a component](./docs/adding-a-component.md) — rules, checklist, required companions
54
+ Dark mode is the same story: remap the tokens under `.dark` (health-assistant
55
+ ships a class-based dark theme this way) no component rewrites. Overlay
56
+ stacking is token-driven too (`--as-z-modal`, `--as-z-popover`) so library
57
+ dialogs clear your app chrome. Full guide: [docs/theming.md](./docs/theming.md).
65
58
 
66
59
  ## Components
67
60
 
@@ -74,26 +67,25 @@ files in the package's `dist/`. Visual reference:
74
67
  | Module | Exports |
75
68
  |---|---|
76
69
  | `button` / `badge` / `card` | `Button`, `buttonVariants` · `Badge`, `badgeVariants` · `Card`, `CardHeader/Title/Description/Content/Footer` |
77
- | `modal` / `confirmation-modal` / `form-modal` | `Modal` + parts, `modalContentVariants` · `ConfirmationModal` · `FormModal` (form-in-modal shell) |
70
+ | `modal` / `panel-modal` | `Modal` + parts (compound Radix dialog) · `PanelModal` (header/body/footer shell, full-screen on mobile) |
71
+ | `confirmation-modal` / `form-modal` | `ConfirmationModal` · `FormModal` (form-in-modal shell: `headerActions`, reject button, busy states) |
78
72
  | `popover` / `popover-button` | compound Radix `Popover` + parts · `PopoverButton` (self-contained trigger + panel, hover-open, lazy children, `closeSignal`) |
79
73
  | `menu` / `context-menu` | `Menu`, `MenuTrigger/Content/Item/Separator/Label`, `ActionMenu` (items-driven) · `ContextMenu` (coordinate-anchored, `{x, y, items, onClose}`) |
80
- | `combobox` | `Combobox`, `ComboboxMulti` — async mode (`onSearchChange` + `loading`), grouping, full keyboard nav |
74
+ | `combobox` | `Combobox`, `ComboboxMulti` — async mode (`onSearchChange` + `loading`), grouping, capability badges, full keyboard nav |
81
75
  | `tooltip` | `Tooltip` + parts, `InfoTooltip` |
82
76
  | `wizard` | `Wizard` (steps config + `renderStep`, per-step validation gates, modal/drawer variants), `Stepper` (dots/labels) |
83
- | `input` / `search-input` / `expandable-search` | `Input` (label/hint/error wiring) · `SearchInput` · `ExpandableSearch` |
77
+ | `input` / `textarea` / `search-input` / `expandable-search` | `Input` (label/hint/error wiring) · `Textarea` · `SearchInput` · `ExpandableSearch` |
84
78
  | `chip-input` / `chip-list` | `ChipInput` (Enter/comma commit, paste-splits, Backspace-removes) · `ChipList` (variant pills, clickable, removable) |
85
- | `time-picker` / `time-list` | `TimePicker` (clock face, 24h value, 12h UI) · `TimeList` (time chips) |
86
- | `date-picker` | `DatePicker` (popover calendar: days/months/years views, min/max, `allowClear`, arrow-key day grid) |
79
+ | `time-picker` / `time-list` | `TimePicker` (clock face, 24h value, 12h UI, editable fields) · `TimeList` (time chips with per-chip pickers) |
80
+ | `date-picker` | `DatePicker` (popover calendar: days/months/years views, min/max, `allowClear`, arrow-key day grid, `unstyled` variant) |
87
81
  | `range-bar` / `scale-slider` | `RangeBar` (low–high band + value dot) · `ScaleSlider` (+ `scaleColorForValue`) |
88
- | `table` | `Table` (headers/rows, built-in empty state) |
82
+ | `table` | `Table` (headers/rows, opt-in empty state) |
89
83
  | `check-indicator` / `selection-bar` / `view-toggle` | `CheckIndicator` (tri-state) · `SelectionBar` (bulk-select bar) · `ViewToggle` (grid/list) |
90
84
  | `error-banner` / `undo-notice` / `empty-state` / `spinner` | presentational feedback: alert banner with `action` slot · undo toast · `EmptyState` · `Spinner` |
91
- | `info-button` / `field-label` | `InfoButton` (info popover) · `FieldLabel` (label + info affordance) |
85
+ | `info-button` / `field-label` / `copy-button` / `breadcrumbs` | `InfoButton` · `FieldLabel` · `CopyButton` (clipboard + copied state) · `Breadcrumbs` (SPA links via `linkComponent`) |
86
+ | `ai-button` / `ai-actions-dropdown` / `ai-magic-fill` | AI affordances: ask-with-suggestions (controlled open, icon-only mode) · action menu + custom prompt · describe-in-words fill modal — API calls stay app-side |
87
+ | `settings-shell` / `provider-form` / `connection-test-row` | `SettingsShell` (controlled two-pane nav) · `ProviderForm` (write-only API-key field) · `ConnectionTestRow` (idle/testing/ok/fail + latency) |
92
88
  | `model-picker` / `task-assignment-picker` | `ModelPicker` (grouped provider→model combobox, capability chips) · `TaskAssignmentPicker` (task → model mapping rows) |
93
- | `settings-shell` / `provider-form` / `connection-test-row` | `SettingsShell` (controlled two-pane nav) · `ProviderForm` (write-only key field) · `ConnectionTestRow` (idle/testing/ok/fail) |
94
- | `copy-button` / `breadcrumbs` | `CopyButton` (clipboard + copied state) · `Breadcrumbs` (SPA links via `linkComponent`) |
95
- | `ai-magic-fill` | `AiMagicFill` (describe-in-words → structured data prompt modal; app applies the data) |
96
- | `ai-button` / `ai-actions-dropdown` | `AiButton` (suggestions + prompt + response slot) · `AiActionsDropdown` (action list + custom prompt) |
97
89
  | `upload-dropzone` / `file-card` / `file-queue` | file attachment surface: dropzone (block/row) · card (status, include toggle) · queue (summary + reorder) |
98
90
  | `marquee` | `useMarquee`, `MarqueeSurface`, `MarqueeBand` (rubber-band selection) |
99
91
  | `portal` / `theme-scope` / `tokens` | `Portal` · `ThemeScope` · token name lists + types |
@@ -103,6 +95,14 @@ where it makes sense, refs forwarded everywhere, English label props with
103
95
  defaults (translate at call sites), icons as props. No fetching, no stores,
104
96
  no router — data in, events out.
105
97
 
98
+ ## Documentation
99
+
100
+ - [Adopting in an app](./docs/adoption.md) — the install/switchover recipe each family app follows (incl. the TW3 cascade notes)
101
+ - [Theming](./docs/theming.md) — tokens, app themes, dark mode, styling hooks
102
+ - [Adding a component](./docs/adding-a-component.md) — rules, checklist, required companions
103
+ - [Local development](./docs/local-development.md) — live-test library changes in the family apps without publishing
104
+ - [Publishing](./docs/publishing.md) — the Changesets release flow and CI setup
105
+
106
106
  ## Development
107
107
 
108
108
  ```bash
@@ -112,16 +112,6 @@ pnpm test --watch
112
112
  pnpm verify # lint + typecheck + test + build
113
113
  ```
114
114
 
115
- Testing library changes inside a real app (no publishing needed) — full
116
- guide in [docs/local-development.md](./docs/local-development.md):
117
-
118
- ```bash
119
- pnpm watch # library: rebuild TS + CSS on change
120
- node scripts/dev-link.mjs link <app-dir> # wire app (pnpm override / npm file:)
121
- # ...run the app dev server; reload picks up library changes
122
- node scripts/dev-link.mjs unlink <app-dir> # restore before committing in the app
123
- ```
124
-
125
115
  Releases happen via [Changesets](./CONTRIBUTING.md) — CI publishes, never a
126
116
  laptop.
127
117
 
@@ -213,7 +213,7 @@ var TimeInput = ({
213
213
  onFocus();
214
214
  requestAnimationFrame(() => {
215
215
  const el = document.activeElement;
216
- if (el) el.select();
216
+ if (el && typeof el.select === "function") el.select();
217
217
  });
218
218
  },
219
219
  onBlur: () => {
@@ -459,5 +459,5 @@ var TimePicker = React.forwardRef(
459
459
  );
460
460
 
461
461
  export { TimePicker, TimePickerContent };
462
- //# sourceMappingURL=chunk-ERK53RFJ.js.map
463
- //# sourceMappingURL=chunk-ERK53RFJ.js.map
462
+ //# sourceMappingURL=chunk-CR42EAF4.js.map
463
+ //# sourceMappingURL=chunk-CR42EAF4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/time-picker/TimePicker.tsx"],"names":["TimePicker","ClockIcon"],"mappings":"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","file":"chunk-CR42EAF4.js","sourcesContent":["import * as React from 'react'\nimport { Check, Clock as ClockIcon } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Popover, PopoverContent, PopoverTrigger } from '../popover'\n\ntype ViewMode = 'hours' | 'minutes'\n\nexport interface TimePickerProps {\n /** 24-hour `HH:MM` string, or null/undefined when empty. */\n value: string | null | undefined\n /** Fired with a 24-hour `HH:MM` string. */\n onChange: (value: string) => void\n className?: string\n placeholder?: string\n disabled?: boolean\n id?: string\n /** Diameter of the clock face in px (default 240). */\n size?: number\n /** Accessible name for the trigger (also an optional visible label). */\n label?: string\n hourLabel?: string\n minuteLabel?: string\n doneLabel?: string\n variant?: 'default' | 'unstyled'\n}\n\ninterface Hms {\n hour24: number\n minute: number\n}\n\nfunction parse24(value: string | null | undefined): Hms | null {\n if (!value) return null\n const m = /^(\\d{1,2}):(\\d{1,2})$/.exec(value.trim())\n if (!m) return null\n const h = parseInt(m[1]!, 10)\n const min = parseInt(m[2]!, 10)\n if (Number.isNaN(h) || Number.isNaN(min) || h < 0 || h > 23 || min < 0 || min > 59) return null\n return { hour24: h, minute: min }\n}\n\nfunction to24(hour12: number, period: 'AM' | 'PM'): number {\n if (period === 'AM') return hour12 === 12 ? 0 : hour12\n return hour12 === 12 ? 12 : hour12 + 12\n}\n\nfunction from24(hour24: number): { hour12: number; period: 'AM' | 'PM' } {\n if (hour24 === 0) return { hour12: 12, period: 'AM' }\n if (hour24 === 12) return { hour12: 12, period: 'PM' }\n if (hour24 < 12) return { hour12: hour24, period: 'AM' }\n return { hour12: hour24 - 12, period: 'PM' }\n}\n\nfunction format12(hour24: number, minute: number): string {\n const { hour12, period } = from24(hour24)\n const mm = minute.toString().padStart(2, '0')\n return `${hour12}:${mm} ${period}`\n}\n\nfunction format24(hour24: number, minute: number): string {\n return `${hour24.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`\n}\n\ninterface ClockProps {\n mode: ViewMode\n hour12: number\n minute: number\n size: number\n onPickHour: (h: number) => void\n onPickMinute: (m: number) => void\n}\n\n/**\n * SVG clock face. Hours (1–12) and minutes (0,5,…,55) sit on a ring; the\n * selected tick is highlighted and a hand points to it. Click anywhere on the\n * face to snap to the nearest tick of the active mode.\n */\nconst ClockFace: React.FC<ClockProps> = ({\n mode,\n hour12,\n minute,\n size,\n onPickHour,\n onPickMinute,\n}) => {\n const cx = size / 2\n const cy = size / 2\n const radius = size / 2 - 22\n\n const ticks =\n mode === 'hours'\n ? Array.from({ length: 12 }, (_, i) => i + 1)\n : Array.from({ length: 12 }, (_, i) => i * 5)\n\n const selectedValue = mode === 'hours' ? hour12 : minute\n\n const angleFor = React.useCallback(\n (val: number) => {\n if (mode === 'hours') {\n return (val / 12) * 360 - 90\n }\n return (val / 60) * 360 - 90\n },\n [mode],\n )\n\n const pointFor = React.useCallback(\n (val: number, r: number) => {\n const rad = (angleFor(val) * Math.PI) / 180\n return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) }\n },\n [angleFor, cx, cy],\n )\n\n const handTarget = pointFor(selectedValue, radius - 22)\n const labelPoint = (val: number) => pointFor(val, radius)\n\n const handleClick = (e: React.MouseEvent<SVGSVGElement>) => {\n const svg = e.currentTarget\n const rect = svg.getBoundingClientRect()\n const x = e.clientX - rect.left - cx\n const y = e.clientY - rect.top - cy\n let deg = (Math.atan2(y, x) * 180) / Math.PI + 90\n if (deg < 0) deg += 360\n if (mode === 'hours') {\n const h = Math.round(deg / 30) || 12\n onPickHour(h)\n } else {\n const m = (Math.round(deg / 30) || 12) * 5\n onPickMinute(m === 60 ? 0 : m)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<SVGSVGElement>) => {\n if (mode === 'hours') {\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault()\n onPickHour(hour12 >= 12 ? 1 : hour12 + 1)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault()\n onPickHour(hour12 <= 1 ? 12 : hour12 - 1)\n }\n } else {\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault()\n onPickMinute(minute >= 55 ? 0 : minute + 5)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault()\n onPickMinute(minute <= 0 ? 55 : minute - 5)\n }\n }\n }\n\n return (\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n tabIndex={0}\n role=\"slider\"\n aria-label={mode === 'hours' ? 'Hour' : 'Minute'}\n aria-valuemin={mode === 'hours' ? 1 : 0}\n aria-valuemax={mode === 'hours' ? 12 : 59}\n aria-valuenow={selectedValue}\n className=\"cursor-pointer rounded-full outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)]\"\n >\n <circle cx={cx} cy={cy} r={radius + 4} className=\"fill-[var(--as-muted)] stroke-[var(--as-border)]\" strokeWidth={1} />\n\n {ticks.map((val) => {\n const p = labelPoint(val)\n const isSelected = val === selectedValue\n return (\n <g key={val}>\n <circle\n cx={p.x}\n cy={p.y}\n r={isSelected ? 17 : 15}\n className={cn(\n 'transition-all',\n isSelected\n ? 'fill-[var(--as-primary)]'\n : 'fill-[var(--as-surface-raised)] stroke-[var(--as-border)]',\n )}\n strokeWidth={1}\n />\n <text\n x={p.x}\n y={p.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className={cn(\n 'font-medium',\n isSelected ? 'fill-[var(--as-primary-fg)] font-bold' : 'fill-[var(--as-fg)]',\n )}\n style={{ fontSize: 13, userSelect: 'none' }}\n >\n {val.toString().padStart(2, '0')}\n </text>\n </g>\n )\n })}\n\n <line\n x1={cx}\n y1={cy}\n x2={handTarget.x}\n y2={handTarget.y}\n className=\"stroke-[var(--as-primary)]\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n />\n <circle cx={cx} cy={cy} r={5} className=\"fill-[var(--as-primary)]\" />\n </svg>\n )\n}\n\ninterface TimeInputProps {\n value: number\n min: number\n max: number\n active?: boolean\n onChange: (n: number) => void\n onFocus: () => void\n onConvertFrom24?: (n24: number) => void\n ariaLabel?: string\n}\n\n/**\n * A 2-digit, keyboard-editable numeric field. Accepts only digits, clamps on\n * blur/Enter, and supports Arrow Up/Down to step. While focused it holds the\n * raw text; it re-syncs from `value` when not focused.\n */\nconst TimeInput: React.FC<TimeInputProps> = ({\n value,\n min,\n max,\n active,\n onChange,\n onFocus,\n onConvertFrom24,\n ariaLabel,\n}) => {\n const pad = (n: number) => n.toString().padStart(2, '0')\n const [text, setText] = React.useState<string>(pad(value))\n const [focused, setFocused] = React.useState(false)\n\n React.useEffect(() => {\n if (!focused) setText(pad(value))\n }, [value, focused])\n\n const commit = (raw: string) => {\n const digits = raw.replace(/\\D/g, '')\n if (digits === '') {\n setText(pad(value))\n return\n }\n const n = parseInt(digits, 10)\n if (Number.isNaN(n)) {\n setText(pad(value))\n return\n }\n if (onConvertFrom24 && (n > max || n === 0)) {\n onConvertFrom24(n)\n return\n }\n const clamped = Math.max(min, Math.min(max, n))\n onChange(clamped)\n setText(pad(clamped))\n }\n\n return (\n <input\n type=\"text\"\n inputMode=\"numeric\"\n pattern=\"[0-9]*\"\n maxLength={2}\n value={text}\n aria-label={ariaLabel}\n onFocus={() => {\n setFocused(true)\n onFocus()\n requestAnimationFrame(() => {\n const el = document.activeElement as HTMLInputElement | null\n if (el && typeof el.select === 'function') el.select()\n })\n }}\n onBlur={() => {\n setFocused(false)\n commit(text)\n }}\n onChange={(e) => setText(e.target.value.replace(/\\D/g, '').slice(0, 2))}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n ;(e.target as HTMLInputElement).blur()\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n const next = value >= max ? min : value + 1\n onChange(next)\n } else if (e.key === 'ArrowDown') {\n e.preventDefault()\n const next = value <= min ? max : value - 1\n onChange(next)\n }\n }}\n className={cn(\n 'h-10 w-12 rounded-[var(--as-radius-sm)] bg-transparent text-center text-2xl font-bold tabular-nums outline-none transition-colors',\n active\n ? 'bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] text-[var(--as-primary)]'\n : 'text-[var(--as-fg)] hover:bg-[var(--as-muted)]',\n )}\n />\n )\n}\n\nexport interface TimePickerContentProps {\n value: string | null | undefined\n onChange: (value: string) => void\n onDone?: () => void\n size?: number\n hourLabel?: string\n minuteLabel?: string\n doneLabel?: string\n className?: string\n}\n\n/**\n * The popover body: editable HH:MM inputs + AM/PM segmented control + clock\n * face + Done button. Owns a working copy of the time, seeded from `value`\n * once on mount (the parent unmounts it when the popover closes).\n */\nexport const TimePickerContent: React.FC<TimePickerContentProps> = ({\n value,\n onChange,\n onDone,\n size = 240,\n hourLabel = 'Hour',\n minuteLabel = 'Minute',\n doneLabel = 'Done',\n className,\n}) => {\n const seedRef = React.useRef<{ h24: number; min: number } | null>(null)\n if (seedRef.current === null) {\n const p = parse24(value)\n if (p) {\n seedRef.current = { h24: p.hour24, min: p.minute }\n } else {\n const now = new Date()\n seedRef.current = { h24: now.getHours(), min: now.getMinutes() }\n }\n }\n const seed = seedRef.current\n\n const [hour12, setHour12] = React.useState<number>(() => from24(seed.h24).hour12)\n const [minute, setMinute] = React.useState<number>(seed.min)\n const [period, setPeriod] = React.useState<'AM' | 'PM'>(() => from24(seed.h24).period)\n const [mode, setMode] = React.useState<ViewMode>('hours')\n\n const commit = React.useCallback(\n (h12: number, min: number, p: 'AM' | 'PM') => {\n onChange(format24(to24(h12, p), min))\n },\n [onChange],\n )\n\n const pickHour = (h: number) => {\n setHour12(h)\n commit(h, minute, period)\n }\n const pickMinute = (m: number) => {\n setMinute(m)\n commit(hour12, m, period)\n }\n const togglePeriod = (p: 'AM' | 'PM') => {\n if (p === period) return\n setPeriod(p)\n commit(hour12, minute, p)\n }\n\n return (\n <div\n data-as=\"time-picker-content\"\n className={cn('flex flex-col gap-2 p-4', className)}\n >\n <div className=\"mb-1 flex select-none items-center justify-center gap-2\">\n <div className=\"flex items-center gap-0.5 rounded-[var(--as-radius)] bg-[var(--as-muted)] px-1 py-0.5\">\n <TimeInput\n value={hour12}\n min={1}\n max={12}\n active={mode === 'hours'}\n ariaLabel={hourLabel}\n onChange={(h) => {\n setHour12(h)\n commit(h, minute, period)\n }}\n onConvertFrom24={(n24) => {\n const f = from24(n24)\n setHour12(f.hour12)\n setPeriod(f.period)\n commit(f.hour12, minute, f.period)\n }}\n onFocus={() => setMode('hours')}\n />\n <span className=\"px-0.5 text-2xl font-bold text-[var(--as-muted-fg)]\">:</span>\n <TimeInput\n value={minute}\n min={0}\n max={59}\n active={mode === 'minutes'}\n ariaLabel={minuteLabel}\n onChange={(m) => {\n setMinute(m)\n commit(hour12, m, period)\n }}\n onFocus={() => setMode('minutes')}\n />\n </div>\n\n <div className=\"flex overflow-hidden rounded-[var(--as-radius)] border border-[var(--as-border)]\">\n {(['AM', 'PM'] as const).map((p) => (\n <button\n key={p}\n type=\"button\"\n onClick={() => togglePeriod(p)}\n aria-pressed={period === p}\n className={cn(\n 'cursor-pointer px-3 py-1.5 text-xs font-bold uppercase tracking-widest transition-colors',\n period === p\n ? 'bg-[var(--as-primary)] text-[var(--as-primary-fg)]'\n : 'bg-[var(--as-surface)] text-[var(--as-muted-fg)] hover:bg-[var(--as-muted)]',\n )}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n\n <p className=\"mb-1 text-center text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]\">\n {mode === 'hours' ? hourLabel : minuteLabel}\n </p>\n\n <div className=\"mb-2 flex justify-center\">\n <ClockFace\n mode={mode}\n hour12={hour12}\n minute={minute}\n size={size}\n onPickHour={pickHour}\n onPickMinute={pickMinute}\n />\n </div>\n\n <div className=\"flex justify-end border-t border-[var(--as-border)] pt-2\">\n <button\n type=\"button\"\n onClick={onDone}\n className=\"flex cursor-pointer items-center gap-1.5 rounded-[var(--as-radius)] bg-[var(--as-primary)] px-4 py-2 text-xs font-bold text-[var(--as-primary-fg)] transition-[filter] hover:brightness-110\"\n >\n <Check className=\"size-3.5\" aria-hidden />\n {doneLabel}\n </button>\n </div>\n </div>\n )\n}\n\nexport const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>(\n function TimePicker(\n {\n value,\n onChange,\n className,\n placeholder = 'Select time',\n disabled = false,\n id,\n size = 240,\n label,\n hourLabel,\n minuteLabel,\n doneLabel,\n variant = 'default',\n },\n ref,\n ) {\n const [open, setOpen] = React.useState(false)\n\n const parsed = parse24(value)\n const display = parsed ? format12(parsed.hour24, parsed.minute) : null\n\n return (\n <div\n ref={ref}\n data-as=\"time-picker\"\n className={cn(!className?.includes('w-') && 'w-full', 'flex flex-col', className)}\n >\n {label ? (\n <label className=\"mb-1.5 ml-1 block text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]\">\n {label}\n </label>\n ) : null}\n <Popover open={open && !disabled} onOpenChange={setOpen}>\n <PopoverTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n aria-label={label ?? 'Choose time'}\n className={cn(\n 'flex items-center gap-2 text-left text-sm outline-none transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50',\n !className?.includes('w-') && 'w-full',\n variant === 'default' &&\n 'rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2.5 hover:border-[var(--as-primary)]',\n )}\n >\n {variant === 'default' ? (\n <ClockIcon className=\"size-4 shrink-0 text-[var(--as-muted-fg)]\" aria-hidden />\n ) : null}\n <span\n className={cn(\n 'flex-1 truncate',\n !parsed && (variant === 'default' ? 'text-[var(--as-muted-fg)]' : 'opacity-70'),\n parsed && variant === 'default' && 'font-medium text-[var(--as-fg)]',\n )}\n >\n {display ?? placeholder}\n </span>\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n sideOffset={4}\n collisionPadding={8}\n aria-label={label ?? 'Choose time'}\n className=\"w-[300px] p-0\"\n >\n <TimePickerContent\n value={value}\n onChange={onChange}\n onDone={() => setOpen(false)}\n size={size}\n hourLabel={hourLabel}\n minuteLabel={minuteLabel}\n doneLabel={doneLabel}\n />\n </PopoverContent>\n </Popover>\n\n <input type=\"hidden\" value={value ?? ''} id={id} name={id} />\n </div>\n )\n },\n)\n"]}
@@ -1,4 +1,4 @@
1
- import { TimePickerContent } from './chunk-ERK53RFJ.js';
1
+ import { TimePickerContent } from './chunk-CR42EAF4.js';
2
2
  import { Popover, PopoverTrigger, PopoverContent } from './chunk-SIIY2EGI.js';
3
3
  import { cn } from './chunk-BLJWR4ZV.js';
4
4
  import * as React from 'react';
@@ -159,5 +159,5 @@ var TimeList = React.forwardRef(
159
159
  );
160
160
 
161
161
  export { TimeList };
162
- //# sourceMappingURL=chunk-TJLELOAW.js.map
163
- //# sourceMappingURL=chunk-TJLELOAW.js.map
162
+ //# sourceMappingURL=chunk-GVOC3ARM.js.map
163
+ //# sourceMappingURL=chunk-GVOC3ARM.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/time-list/TimeList.tsx"],"names":["ClockIcon","TimeList"],"mappings":"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","file":"chunk-TJLELOAW.js","sourcesContent":["import * as React from 'react'\nimport { Clock as ClockIcon, Plus, X } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Popover, PopoverContent, PopoverTrigger } from '../popover'\nimport { TimePickerContent } from '../time-picker/TimePicker'\n\nexport interface TimeListProps {\n /** List of 24-hour `HH:MM` strings. */\n value: string[]\n /** Push the fully replaced list back to the parent. */\n onChange: (next: string[]) => void\n /** Optional heading rendered above the chips. */\n label?: string\n /** Optional helper text rendered under the label. */\n hint?: string\n addLabel?: string\n emptyLabel?: string\n /** Cap the number of chips; renders a note when reached. */\n maxItems?: number\n maxItemsLabel?: (n: number) => string\n removeLabel?: string\n /** Disable every chip + the add button. */\n disabled?: boolean\n /** Diameter of the picker's clock face (default 220). */\n clockSize?: number\n className?: string\n}\n\nfunction readTime(value: string): { h12: number; min: number; period: 'AM' | 'PM' } | null {\n const m = /^(\\d{1,2}):(\\d{1,2})$/.exec((value || '').trim())\n if (!m) return null\n const h = parseInt(m[1]!, 10)\n const min = parseInt(m[2]!, 10)\n if (Number.isNaN(h) || Number.isNaN(min) || h < 0 || h > 23 || min < 0 || min > 59) return null\n const period: 'AM' | 'PM' = h < 12 ? 'AM' : 'PM'\n const h12 = h === 0 ? 12 : h > 12 ? h - 12 : h\n return { h12, min, period }\n}\n\ninterface ChipProps {\n value: string\n onChange: (v: string) => void\n onRemove: () => void\n clockSize: number\n removeLabel: string\n disabled?: boolean\n}\n\nconst TimeChip: React.FC<ChipProps> = ({\n value,\n onChange,\n onRemove,\n clockSize,\n removeLabel,\n disabled,\n}) => {\n const [open, setOpen] = React.useState(false)\n const parsed = readTime(value ?? '')\n\n const main = parsed ? parsed.h12.toString() : '--'\n const minStr = parsed ? parsed.min.toString().padStart(2, '0') : '--'\n const period = parsed ? parsed.period : ''\n\n return (\n <Popover open={open && !disabled} onOpenChange={setOpen}>\n <span className=\"relative inline-flex group\">\n <PopoverTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n aria-label={`Edit ${value}`}\n className={cn(\n 'inline-flex cursor-pointer select-none items-center gap-2 rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] py-2 pl-3 pr-7 transition-[border-color,box-shadow,translate] hover:border-[var(--as-primary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n !disabled && 'hover:-translate-y-0.5 hover:shadow-[var(--as-shadow-2)]',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n >\n <span className=\"flex size-7 shrink-0 items-center justify-center rounded-[var(--as-radius-sm)] bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] text-[var(--as-primary)]\">\n <ClockIcon className=\"size-4\" aria-hidden />\n </span>\n <span className=\"flex items-baseline gap-1 tabular-nums\">\n <span className=\"text-base font-extrabold leading-none text-[var(--as-fg)]\">\n {main}:{minStr}\n </span>\n {period ? (\n <span className=\"text-[10px] font-bold uppercase tracking-wider text-[var(--as-muted-fg)]\">\n {period}\n </span>\n ) : null}\n </span>\n </button>\n </PopoverTrigger>\n {!disabled ? (\n <button\n type=\"button\"\n aria-label={removeLabel}\n onClick={(e) => {\n e.stopPropagation()\n onRemove()\n }}\n className=\"absolute right-1.5 top-1/2 z-10 flex size-5 cursor-pointer items-center justify-center rounded-full bg-[var(--as-surface-raised)] text-[var(--as-muted-fg)] opacity-0 transition-all hover:bg-[var(--as-danger)] hover:text-[var(--as-danger-fg)] focus-visible:opacity-100 group-hover:opacity-100\"\n style={{ translate: '0 -50%' }}\n >\n <X className=\"size-3\" aria-hidden />\n </button>\n ) : null}\n <PopoverContent\n align=\"center\"\n sideOffset={6}\n collisionPadding={8}\n aria-label={`Edit ${value}`}\n className=\"w-[300px] p-0\"\n >\n <TimePickerContent\n value={value}\n onChange={onChange}\n onDone={() => setOpen(false)}\n size={clockSize}\n />\n </PopoverContent>\n </span>\n </Popover>\n )\n}\n\n/**\n * Chip-based editor for a list of `HH:MM` times: each chip opens the clock\n * picker, an add pill appends a slot. For a single time use `TimePicker`.\n */\nexport const TimeList = React.forwardRef<HTMLDivElement, TimeListProps>(\n function TimeList(\n {\n value,\n onChange,\n label,\n hint,\n addLabel = 'Add time',\n emptyLabel,\n maxItems,\n maxItemsLabel = (n) => `Maximum of ${n} items.`,\n removeLabel = 'Remove time',\n disabled = false,\n clockSize = 220,\n className,\n },\n ref,\n ) {\n const updateAt = React.useCallback(\n (i: number, v: string) => {\n if (disabled) return\n const next = value.slice()\n next[i] = v\n onChange(next)\n },\n [disabled, value, onChange],\n )\n\n const removeAt = React.useCallback(\n (i: number) => {\n if (disabled) return\n onChange(value.filter((_, idx) => idx !== i))\n },\n [disabled, value, onChange],\n )\n\n const add = React.useCallback(() => {\n if (disabled) return\n if (maxItems !== undefined && value.length >= maxItems) return\n onChange([...value, '09:00'])\n }, [disabled, maxItems, value, onChange])\n\n const atMax = maxItems !== undefined && value.length >= maxItems\n\n return (\n <div ref={ref} data-as=\"time-list\" className={cn('flex flex-col gap-2', className)}>\n {label || hint ? (\n <div>\n {label ? (\n <p className=\"px-1 text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]\">\n {label}\n </p>\n ) : null}\n {hint ? (\n <p className=\"mt-0.5 px-1 text-[11px] text-[var(--as-muted-fg)]\">{hint}</p>\n ) : null}\n </div>\n ) : null}\n\n {value.length === 0 && emptyLabel ? (\n <p className=\"px-1 py-2 text-xs italic text-[var(--as-muted-fg)]\">{emptyLabel}</p>\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {value.map((time, i) => (\n <TimeChip\n key={`${i}-${time}`}\n value={time}\n onChange={(v) => updateAt(i, v)}\n onRemove={() => removeAt(i)}\n clockSize={clockSize}\n removeLabel={removeLabel}\n disabled={disabled}\n />\n ))}\n </div>\n )}\n\n {!atMax && !disabled ? (\n <button\n type=\"button\"\n onClick={add}\n className=\"inline-flex cursor-pointer items-center gap-1.5 rounded-[var(--as-radius)] border border-dashed border-[var(--as-border)] py-1.5 pl-2.5 pr-3 text-xs font-bold text-[var(--as-muted-fg)] transition-colors hover:border-[var(--as-primary)] hover:bg-[color-mix(in_srgb,var(--as-primary)_6%,transparent)] hover:text-[var(--as-primary)]\"\n >\n <Plus className=\"size-3.5\" aria-hidden />\n {addLabel}\n </button>\n ) : null}\n\n {atMax && maxItems !== undefined ? (\n <p className=\"text-[10px] italic text-[var(--as-muted-fg)]\">{maxItemsLabel(maxItems)}</p>\n ) : null}\n </div>\n )\n },\n)\n"]}
1
+ {"version":3,"sources":["../src/components/time-list/TimeList.tsx"],"names":["ClockIcon","TimeList"],"mappings":"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","file":"chunk-GVOC3ARM.js","sourcesContent":["import * as React from 'react'\nimport { Clock as ClockIcon, Plus, X } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Popover, PopoverContent, PopoverTrigger } from '../popover'\nimport { TimePickerContent } from '../time-picker/TimePicker'\n\nexport interface TimeListProps {\n /** List of 24-hour `HH:MM` strings. */\n value: string[]\n /** Push the fully replaced list back to the parent. */\n onChange: (next: string[]) => void\n /** Optional heading rendered above the chips. */\n label?: string\n /** Optional helper text rendered under the label. */\n hint?: string\n addLabel?: string\n emptyLabel?: string\n /** Cap the number of chips; renders a note when reached. */\n maxItems?: number\n maxItemsLabel?: (n: number) => string\n removeLabel?: string\n /** Disable every chip + the add button. */\n disabled?: boolean\n /** Diameter of the picker's clock face (default 220). */\n clockSize?: number\n className?: string\n}\n\nfunction readTime(value: string): { h12: number; min: number; period: 'AM' | 'PM' } | null {\n const m = /^(\\d{1,2}):(\\d{1,2})$/.exec((value || '').trim())\n if (!m) return null\n const h = parseInt(m[1]!, 10)\n const min = parseInt(m[2]!, 10)\n if (Number.isNaN(h) || Number.isNaN(min) || h < 0 || h > 23 || min < 0 || min > 59) return null\n const period: 'AM' | 'PM' = h < 12 ? 'AM' : 'PM'\n const h12 = h === 0 ? 12 : h > 12 ? h - 12 : h\n return { h12, min, period }\n}\n\ninterface ChipProps {\n value: string\n onChange: (v: string) => void\n onRemove: () => void\n clockSize: number\n removeLabel: string\n disabled?: boolean\n}\n\nconst TimeChip: React.FC<ChipProps> = ({\n value,\n onChange,\n onRemove,\n clockSize,\n removeLabel,\n disabled,\n}) => {\n const [open, setOpen] = React.useState(false)\n const parsed = readTime(value ?? '')\n\n const main = parsed ? parsed.h12.toString() : '--'\n const minStr = parsed ? parsed.min.toString().padStart(2, '0') : '--'\n const period = parsed ? parsed.period : ''\n\n return (\n <Popover open={open && !disabled} onOpenChange={setOpen}>\n <span className=\"relative inline-flex group\">\n <PopoverTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n aria-label={`Edit ${value}`}\n className={cn(\n 'inline-flex cursor-pointer select-none items-center gap-2 rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface-raised)] py-2 pl-3 pr-7 transition-[border-color,box-shadow,translate] hover:border-[var(--as-primary)] focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)]',\n !disabled && 'hover:-translate-y-0.5 hover:shadow-[var(--as-shadow-2)]',\n disabled && 'cursor-not-allowed opacity-50',\n )}\n >\n <span className=\"flex size-7 shrink-0 items-center justify-center rounded-[var(--as-radius-sm)] bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] text-[var(--as-primary)]\">\n <ClockIcon className=\"size-4\" aria-hidden />\n </span>\n <span className=\"flex items-baseline gap-1 tabular-nums\">\n <span className=\"text-base font-extrabold leading-none text-[var(--as-fg)]\">\n {main}:{minStr}\n </span>\n {period ? (\n <span className=\"text-[10px] font-bold uppercase tracking-wider text-[var(--as-muted-fg)]\">\n {period}\n </span>\n ) : null}\n </span>\n </button>\n </PopoverTrigger>\n {!disabled ? (\n <button\n type=\"button\"\n aria-label={removeLabel}\n onClick={(e) => {\n e.stopPropagation()\n onRemove()\n }}\n className=\"absolute right-1.5 top-1/2 z-10 flex size-5 cursor-pointer items-center justify-center rounded-full bg-[var(--as-surface-raised)] text-[var(--as-muted-fg)] opacity-0 transition-all hover:bg-[var(--as-danger)] hover:text-[var(--as-danger-fg)] focus-visible:opacity-100 group-hover:opacity-100\"\n style={{ translate: '0 -50%' }}\n >\n <X className=\"size-3\" aria-hidden />\n </button>\n ) : null}\n <PopoverContent\n align=\"center\"\n sideOffset={6}\n collisionPadding={8}\n aria-label={`Edit ${value}`}\n className=\"w-[300px] p-0\"\n >\n <TimePickerContent\n value={value}\n onChange={onChange}\n onDone={() => setOpen(false)}\n size={clockSize}\n />\n </PopoverContent>\n </span>\n </Popover>\n )\n}\n\n/**\n * Chip-based editor for a list of `HH:MM` times: each chip opens the clock\n * picker, an add pill appends a slot. For a single time use `TimePicker`.\n */\nexport const TimeList = React.forwardRef<HTMLDivElement, TimeListProps>(\n function TimeList(\n {\n value,\n onChange,\n label,\n hint,\n addLabel = 'Add time',\n emptyLabel,\n maxItems,\n maxItemsLabel = (n) => `Maximum of ${n} items.`,\n removeLabel = 'Remove time',\n disabled = false,\n clockSize = 220,\n className,\n },\n ref,\n ) {\n const updateAt = React.useCallback(\n (i: number, v: string) => {\n if (disabled) return\n const next = value.slice()\n next[i] = v\n onChange(next)\n },\n [disabled, value, onChange],\n )\n\n const removeAt = React.useCallback(\n (i: number) => {\n if (disabled) return\n onChange(value.filter((_, idx) => idx !== i))\n },\n [disabled, value, onChange],\n )\n\n const add = React.useCallback(() => {\n if (disabled) return\n if (maxItems !== undefined && value.length >= maxItems) return\n onChange([...value, '09:00'])\n }, [disabled, maxItems, value, onChange])\n\n const atMax = maxItems !== undefined && value.length >= maxItems\n\n return (\n <div ref={ref} data-as=\"time-list\" className={cn('flex flex-col gap-2', className)}>\n {label || hint ? (\n <div>\n {label ? (\n <p className=\"px-1 text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]\">\n {label}\n </p>\n ) : null}\n {hint ? (\n <p className=\"mt-0.5 px-1 text-[11px] text-[var(--as-muted-fg)]\">{hint}</p>\n ) : null}\n </div>\n ) : null}\n\n {value.length === 0 && emptyLabel ? (\n <p className=\"px-1 py-2 text-xs italic text-[var(--as-muted-fg)]\">{emptyLabel}</p>\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {value.map((time, i) => (\n <TimeChip\n key={`${i}-${time}`}\n value={time}\n onChange={(v) => updateAt(i, v)}\n onRemove={() => removeAt(i)}\n clockSize={clockSize}\n removeLabel={removeLabel}\n disabled={disabled}\n />\n ))}\n </div>\n )}\n\n {!atMax && !disabled ? (\n <button\n type=\"button\"\n onClick={add}\n className=\"inline-flex cursor-pointer items-center gap-1.5 rounded-[var(--as-radius)] border border-dashed border-[var(--as-border)] py-1.5 pl-2.5 pr-3 text-xs font-bold text-[var(--as-muted-fg)] transition-colors hover:border-[var(--as-primary)] hover:bg-[color-mix(in_srgb,var(--as-primary)_6%,transparent)] hover:text-[var(--as-primary)]\"\n >\n <Plus className=\"size-3.5\" aria-hidden />\n {addLabel}\n </button>\n ) : null}\n\n {atMax && maxItems !== undefined ? (\n <p className=\"text-[10px] italic text-[var(--as-muted-fg)]\">{maxItemsLabel(maxItems)}</p>\n ) : null}\n </div>\n )\n },\n)\n"]}
package/dist/index.js CHANGED
@@ -5,8 +5,8 @@ export { Table } from './chunk-5LRRVD27.js';
5
5
  export { TaskAssignmentPicker } from './chunk-TN35RR2R.js';
6
6
  export { SettingsShell } from './chunk-AHLNXCP2.js';
7
7
  export { ThemeScope } from './chunk-TGU3PKNM.js';
8
- export { TimeList } from './chunk-TJLELOAW.js';
9
- export { TimePicker, TimePickerContent } from './chunk-ERK53RFJ.js';
8
+ export { TimeList } from './chunk-GVOC3ARM.js';
9
+ export { TimePicker, TimePickerContent } from './chunk-CR42EAF4.js';
10
10
  export { InfoTooltip, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './chunk-34NO2UOB.js';
11
11
  export { Portal } from './chunk-7YLR4AGA.js';
12
12
  export { ProviderForm } from './chunk-RJSN4TVT.js';
package/dist/time-list.js CHANGED
@@ -1,3 +1,3 @@
1
- export { TimeList } from './chunk-TJLELOAW.js';
1
+ export { TimeList } from './chunk-GVOC3ARM.js';
2
2
  //# sourceMappingURL=time-list.js.map
3
3
  //# sourceMappingURL=time-list.js.map
@@ -1,3 +1,3 @@
1
- export { TimePicker, TimePickerContent } from './chunk-ERK53RFJ.js';
1
+ export { TimePicker, TimePickerContent } from './chunk-CR42EAF4.js';
2
2
  //# sourceMappingURL=time-picker.js.map
3
3
  //# sourceMappingURL=time-picker.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuronection/assistant-ui",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Shared React component library for the Assistant family (career-, study-, health-assistant). Family look by default, app-flavored via CSS-variable tokens.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/time-picker/TimePicker.tsx"],"names":["TimePicker","ClockIcon"],"mappings":"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","file":"chunk-ERK53RFJ.js","sourcesContent":["import * as React from 'react'\nimport { Check, Clock as ClockIcon } from 'lucide-react'\nimport { cn } from '../../lib/utils'\nimport { Popover, PopoverContent, PopoverTrigger } from '../popover'\n\ntype ViewMode = 'hours' | 'minutes'\n\nexport interface TimePickerProps {\n /** 24-hour `HH:MM` string, or null/undefined when empty. */\n value: string | null | undefined\n /** Fired with a 24-hour `HH:MM` string. */\n onChange: (value: string) => void\n className?: string\n placeholder?: string\n disabled?: boolean\n id?: string\n /** Diameter of the clock face in px (default 240). */\n size?: number\n /** Accessible name for the trigger (also an optional visible label). */\n label?: string\n hourLabel?: string\n minuteLabel?: string\n doneLabel?: string\n variant?: 'default' | 'unstyled'\n}\n\ninterface Hms {\n hour24: number\n minute: number\n}\n\nfunction parse24(value: string | null | undefined): Hms | null {\n if (!value) return null\n const m = /^(\\d{1,2}):(\\d{1,2})$/.exec(value.trim())\n if (!m) return null\n const h = parseInt(m[1]!, 10)\n const min = parseInt(m[2]!, 10)\n if (Number.isNaN(h) || Number.isNaN(min) || h < 0 || h > 23 || min < 0 || min > 59) return null\n return { hour24: h, minute: min }\n}\n\nfunction to24(hour12: number, period: 'AM' | 'PM'): number {\n if (period === 'AM') return hour12 === 12 ? 0 : hour12\n return hour12 === 12 ? 12 : hour12 + 12\n}\n\nfunction from24(hour24: number): { hour12: number; period: 'AM' | 'PM' } {\n if (hour24 === 0) return { hour12: 12, period: 'AM' }\n if (hour24 === 12) return { hour12: 12, period: 'PM' }\n if (hour24 < 12) return { hour12: hour24, period: 'AM' }\n return { hour12: hour24 - 12, period: 'PM' }\n}\n\nfunction format12(hour24: number, minute: number): string {\n const { hour12, period } = from24(hour24)\n const mm = minute.toString().padStart(2, '0')\n return `${hour12}:${mm} ${period}`\n}\n\nfunction format24(hour24: number, minute: number): string {\n return `${hour24.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`\n}\n\ninterface ClockProps {\n mode: ViewMode\n hour12: number\n minute: number\n size: number\n onPickHour: (h: number) => void\n onPickMinute: (m: number) => void\n}\n\n/**\n * SVG clock face. Hours (1–12) and minutes (0,5,…,55) sit on a ring; the\n * selected tick is highlighted and a hand points to it. Click anywhere on the\n * face to snap to the nearest tick of the active mode.\n */\nconst ClockFace: React.FC<ClockProps> = ({\n mode,\n hour12,\n minute,\n size,\n onPickHour,\n onPickMinute,\n}) => {\n const cx = size / 2\n const cy = size / 2\n const radius = size / 2 - 22\n\n const ticks =\n mode === 'hours'\n ? Array.from({ length: 12 }, (_, i) => i + 1)\n : Array.from({ length: 12 }, (_, i) => i * 5)\n\n const selectedValue = mode === 'hours' ? hour12 : minute\n\n const angleFor = React.useCallback(\n (val: number) => {\n if (mode === 'hours') {\n return (val / 12) * 360 - 90\n }\n return (val / 60) * 360 - 90\n },\n [mode],\n )\n\n const pointFor = React.useCallback(\n (val: number, r: number) => {\n const rad = (angleFor(val) * Math.PI) / 180\n return { x: cx + r * Math.cos(rad), y: cy + r * Math.sin(rad) }\n },\n [angleFor, cx, cy],\n )\n\n const handTarget = pointFor(selectedValue, radius - 22)\n const labelPoint = (val: number) => pointFor(val, radius)\n\n const handleClick = (e: React.MouseEvent<SVGSVGElement>) => {\n const svg = e.currentTarget\n const rect = svg.getBoundingClientRect()\n const x = e.clientX - rect.left - cx\n const y = e.clientY - rect.top - cy\n let deg = (Math.atan2(y, x) * 180) / Math.PI + 90\n if (deg < 0) deg += 360\n if (mode === 'hours') {\n const h = Math.round(deg / 30) || 12\n onPickHour(h)\n } else {\n const m = (Math.round(deg / 30) || 12) * 5\n onPickMinute(m === 60 ? 0 : m)\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<SVGSVGElement>) => {\n if (mode === 'hours') {\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault()\n onPickHour(hour12 >= 12 ? 1 : hour12 + 1)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault()\n onPickHour(hour12 <= 1 ? 12 : hour12 - 1)\n }\n } else {\n if (e.key === 'ArrowRight' || e.key === 'ArrowUp') {\n e.preventDefault()\n onPickMinute(minute >= 55 ? 0 : minute + 5)\n } else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') {\n e.preventDefault()\n onPickMinute(minute <= 0 ? 55 : minute - 5)\n }\n }\n }\n\n return (\n <svg\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n tabIndex={0}\n role=\"slider\"\n aria-label={mode === 'hours' ? 'Hour' : 'Minute'}\n aria-valuemin={mode === 'hours' ? 1 : 0}\n aria-valuemax={mode === 'hours' ? 12 : 59}\n aria-valuenow={selectedValue}\n className=\"cursor-pointer rounded-full outline-none focus-visible:ring-2 focus-visible:ring-[var(--as-focus-ring)]\"\n >\n <circle cx={cx} cy={cy} r={radius + 4} className=\"fill-[var(--as-muted)] stroke-[var(--as-border)]\" strokeWidth={1} />\n\n {ticks.map((val) => {\n const p = labelPoint(val)\n const isSelected = val === selectedValue\n return (\n <g key={val}>\n <circle\n cx={p.x}\n cy={p.y}\n r={isSelected ? 17 : 15}\n className={cn(\n 'transition-all',\n isSelected\n ? 'fill-[var(--as-primary)]'\n : 'fill-[var(--as-surface-raised)] stroke-[var(--as-border)]',\n )}\n strokeWidth={1}\n />\n <text\n x={p.x}\n y={p.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n className={cn(\n 'font-medium',\n isSelected ? 'fill-[var(--as-primary-fg)] font-bold' : 'fill-[var(--as-fg)]',\n )}\n style={{ fontSize: 13, userSelect: 'none' }}\n >\n {val.toString().padStart(2, '0')}\n </text>\n </g>\n )\n })}\n\n <line\n x1={cx}\n y1={cy}\n x2={handTarget.x}\n y2={handTarget.y}\n className=\"stroke-[var(--as-primary)]\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n />\n <circle cx={cx} cy={cy} r={5} className=\"fill-[var(--as-primary)]\" />\n </svg>\n )\n}\n\ninterface TimeInputProps {\n value: number\n min: number\n max: number\n active?: boolean\n onChange: (n: number) => void\n onFocus: () => void\n onConvertFrom24?: (n24: number) => void\n ariaLabel?: string\n}\n\n/**\n * A 2-digit, keyboard-editable numeric field. Accepts only digits, clamps on\n * blur/Enter, and supports Arrow Up/Down to step. While focused it holds the\n * raw text; it re-syncs from `value` when not focused.\n */\nconst TimeInput: React.FC<TimeInputProps> = ({\n value,\n min,\n max,\n active,\n onChange,\n onFocus,\n onConvertFrom24,\n ariaLabel,\n}) => {\n const pad = (n: number) => n.toString().padStart(2, '0')\n const [text, setText] = React.useState<string>(pad(value))\n const [focused, setFocused] = React.useState(false)\n\n React.useEffect(() => {\n if (!focused) setText(pad(value))\n }, [value, focused])\n\n const commit = (raw: string) => {\n const digits = raw.replace(/\\D/g, '')\n if (digits === '') {\n setText(pad(value))\n return\n }\n const n = parseInt(digits, 10)\n if (Number.isNaN(n)) {\n setText(pad(value))\n return\n }\n if (onConvertFrom24 && (n > max || n === 0)) {\n onConvertFrom24(n)\n return\n }\n const clamped = Math.max(min, Math.min(max, n))\n onChange(clamped)\n setText(pad(clamped))\n }\n\n return (\n <input\n type=\"text\"\n inputMode=\"numeric\"\n pattern=\"[0-9]*\"\n maxLength={2}\n value={text}\n aria-label={ariaLabel}\n onFocus={() => {\n setFocused(true)\n onFocus()\n requestAnimationFrame(() => {\n const el = document.activeElement as HTMLInputElement | null\n if (el) el.select()\n })\n }}\n onBlur={() => {\n setFocused(false)\n commit(text)\n }}\n onChange={(e) => setText(e.target.value.replace(/\\D/g, '').slice(0, 2))}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault()\n ;(e.target as HTMLInputElement).blur()\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n const next = value >= max ? min : value + 1\n onChange(next)\n } else if (e.key === 'ArrowDown') {\n e.preventDefault()\n const next = value <= min ? max : value - 1\n onChange(next)\n }\n }}\n className={cn(\n 'h-10 w-12 rounded-[var(--as-radius-sm)] bg-transparent text-center text-2xl font-bold tabular-nums outline-none transition-colors',\n active\n ? 'bg-[color-mix(in_srgb,var(--as-primary)_12%,transparent)] text-[var(--as-primary)]'\n : 'text-[var(--as-fg)] hover:bg-[var(--as-muted)]',\n )}\n />\n )\n}\n\nexport interface TimePickerContentProps {\n value: string | null | undefined\n onChange: (value: string) => void\n onDone?: () => void\n size?: number\n hourLabel?: string\n minuteLabel?: string\n doneLabel?: string\n className?: string\n}\n\n/**\n * The popover body: editable HH:MM inputs + AM/PM segmented control + clock\n * face + Done button. Owns a working copy of the time, seeded from `value`\n * once on mount (the parent unmounts it when the popover closes).\n */\nexport const TimePickerContent: React.FC<TimePickerContentProps> = ({\n value,\n onChange,\n onDone,\n size = 240,\n hourLabel = 'Hour',\n minuteLabel = 'Minute',\n doneLabel = 'Done',\n className,\n}) => {\n const seedRef = React.useRef<{ h24: number; min: number } | null>(null)\n if (seedRef.current === null) {\n const p = parse24(value)\n if (p) {\n seedRef.current = { h24: p.hour24, min: p.minute }\n } else {\n const now = new Date()\n seedRef.current = { h24: now.getHours(), min: now.getMinutes() }\n }\n }\n const seed = seedRef.current\n\n const [hour12, setHour12] = React.useState<number>(() => from24(seed.h24).hour12)\n const [minute, setMinute] = React.useState<number>(seed.min)\n const [period, setPeriod] = React.useState<'AM' | 'PM'>(() => from24(seed.h24).period)\n const [mode, setMode] = React.useState<ViewMode>('hours')\n\n const commit = React.useCallback(\n (h12: number, min: number, p: 'AM' | 'PM') => {\n onChange(format24(to24(h12, p), min))\n },\n [onChange],\n )\n\n const pickHour = (h: number) => {\n setHour12(h)\n commit(h, minute, period)\n }\n const pickMinute = (m: number) => {\n setMinute(m)\n commit(hour12, m, period)\n }\n const togglePeriod = (p: 'AM' | 'PM') => {\n if (p === period) return\n setPeriod(p)\n commit(hour12, minute, p)\n }\n\n return (\n <div\n data-as=\"time-picker-content\"\n className={cn('flex flex-col gap-2 p-4', className)}\n >\n <div className=\"mb-1 flex select-none items-center justify-center gap-2\">\n <div className=\"flex items-center gap-0.5 rounded-[var(--as-radius)] bg-[var(--as-muted)] px-1 py-0.5\">\n <TimeInput\n value={hour12}\n min={1}\n max={12}\n active={mode === 'hours'}\n ariaLabel={hourLabel}\n onChange={(h) => {\n setHour12(h)\n commit(h, minute, period)\n }}\n onConvertFrom24={(n24) => {\n const f = from24(n24)\n setHour12(f.hour12)\n setPeriod(f.period)\n commit(f.hour12, minute, f.period)\n }}\n onFocus={() => setMode('hours')}\n />\n <span className=\"px-0.5 text-2xl font-bold text-[var(--as-muted-fg)]\">:</span>\n <TimeInput\n value={minute}\n min={0}\n max={59}\n active={mode === 'minutes'}\n ariaLabel={minuteLabel}\n onChange={(m) => {\n setMinute(m)\n commit(hour12, m, period)\n }}\n onFocus={() => setMode('minutes')}\n />\n </div>\n\n <div className=\"flex overflow-hidden rounded-[var(--as-radius)] border border-[var(--as-border)]\">\n {(['AM', 'PM'] as const).map((p) => (\n <button\n key={p}\n type=\"button\"\n onClick={() => togglePeriod(p)}\n aria-pressed={period === p}\n className={cn(\n 'cursor-pointer px-3 py-1.5 text-xs font-bold uppercase tracking-widest transition-colors',\n period === p\n ? 'bg-[var(--as-primary)] text-[var(--as-primary-fg)]'\n : 'bg-[var(--as-surface)] text-[var(--as-muted-fg)] hover:bg-[var(--as-muted)]',\n )}\n >\n {p}\n </button>\n ))}\n </div>\n </div>\n\n <p className=\"mb-1 text-center text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]\">\n {mode === 'hours' ? hourLabel : minuteLabel}\n </p>\n\n <div className=\"mb-2 flex justify-center\">\n <ClockFace\n mode={mode}\n hour12={hour12}\n minute={minute}\n size={size}\n onPickHour={pickHour}\n onPickMinute={pickMinute}\n />\n </div>\n\n <div className=\"flex justify-end border-t border-[var(--as-border)] pt-2\">\n <button\n type=\"button\"\n onClick={onDone}\n className=\"flex cursor-pointer items-center gap-1.5 rounded-[var(--as-radius)] bg-[var(--as-primary)] px-4 py-2 text-xs font-bold text-[var(--as-primary-fg)] transition-[filter] hover:brightness-110\"\n >\n <Check className=\"size-3.5\" aria-hidden />\n {doneLabel}\n </button>\n </div>\n </div>\n )\n}\n\nexport const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>(\n function TimePicker(\n {\n value,\n onChange,\n className,\n placeholder = 'Select time',\n disabled = false,\n id,\n size = 240,\n label,\n hourLabel,\n minuteLabel,\n doneLabel,\n variant = 'default',\n },\n ref,\n ) {\n const [open, setOpen] = React.useState(false)\n\n const parsed = parse24(value)\n const display = parsed ? format12(parsed.hour24, parsed.minute) : null\n\n return (\n <div\n ref={ref}\n data-as=\"time-picker\"\n className={cn(!className?.includes('w-') && 'w-full', 'flex flex-col', className)}\n >\n {label ? (\n <label className=\"mb-1.5 ml-1 block text-[10px] font-bold uppercase tracking-widest text-[var(--as-muted-fg)]\">\n {label}\n </label>\n ) : null}\n <Popover open={open && !disabled} onOpenChange={setOpen}>\n <PopoverTrigger asChild disabled={disabled}>\n <button\n type=\"button\"\n aria-label={label ?? 'Choose time'}\n className={cn(\n 'flex items-center gap-2 text-left text-sm outline-none transition-colors focus-visible:outline-2 focus-visible:outline-offset-1 focus-visible:outline-[var(--as-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50',\n !className?.includes('w-') && 'w-full',\n variant === 'default' &&\n 'rounded-[var(--as-radius)] border border-[var(--as-border)] bg-[var(--as-surface)] px-3 py-2.5 hover:border-[var(--as-primary)]',\n )}\n >\n {variant === 'default' ? (\n <ClockIcon className=\"size-4 shrink-0 text-[var(--as-muted-fg)]\" aria-hidden />\n ) : null}\n <span\n className={cn(\n 'flex-1 truncate',\n !parsed && (variant === 'default' ? 'text-[var(--as-muted-fg)]' : 'opacity-70'),\n parsed && variant === 'default' && 'font-medium text-[var(--as-fg)]',\n )}\n >\n {display ?? placeholder}\n </span>\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n sideOffset={4}\n collisionPadding={8}\n aria-label={label ?? 'Choose time'}\n className=\"w-[300px] p-0\"\n >\n <TimePickerContent\n value={value}\n onChange={onChange}\n onDone={() => setOpen(false)}\n size={size}\n hourLabel={hourLabel}\n minuteLabel={minuteLabel}\n doneLabel={doneLabel}\n />\n </PopoverContent>\n </Popover>\n\n <input type=\"hidden\" value={value ?? ''} id={id} name={id} />\n </div>\n )\n },\n)\n"]}