@columenlabs/lumen-ui 0.1.17 → 0.1.18

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/dist/index.d.ts CHANGED
@@ -16,6 +16,7 @@ export { LumenGeoMap } from './lumen-geo-map.js';
16
16
  export { LumenWidget, type CardControls, type CardLink, LumenSavedWidget } from './lumen-widget.js';
17
17
  export { LumenConfirm, type LumenConfirmProps } from './confirm.js';
18
18
  export { type LumenAuthPoint, LumenAuthHeading, LumenAuthNote, LumenAuthProblem, LumenAuthStage, type LumenAuthStageProps, LumenCodeField, LumenEmailField, LumenPasswordField, LumenStepBar, } from './lumen-auth.js';
19
+ export { LumenDateInput, type LumenDateInputProps, stepDate, } from './lumen-date-input.js';
19
20
  export { LumenChoice, type LumenChoiceOption } from './lumen-choice.js';
20
21
  export { LumenSecret } from './lumen-secret.js';
21
22
  export { RankedBars, StackedBars, StackedColumns } from './lumen-widget-charts.js';
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ export { LumenGeoMap } from './lumen-geo-map.js';
23
23
  export { LumenWidget, LumenSavedWidget } from './lumen-widget.js';
24
24
  export { LumenConfirm } from './confirm.js';
25
25
  export { LumenAuthHeading, LumenAuthNote, LumenAuthProblem, LumenAuthStage, LumenCodeField, LumenEmailField, LumenPasswordField, LumenStepBar, } from './lumen-auth.js';
26
+ export { LumenDateInput, stepDate, } from './lumen-date-input.js';
26
27
  export { LumenChoice } from './lumen-choice.js';
27
28
  export { LumenSecret } from './lumen-secret.js';
28
29
  export { RankedBars, StackedBars, StackedColumns } from './lumen-widget-charts.js';
@@ -0,0 +1,30 @@
1
+ export type LumenDateInputProps = {
2
+ /** The day as ISO `yyyy-mm-dd`, or '' for none. */
3
+ value: string;
4
+ onChange: (iso: string) => void;
5
+ /** Earliest and latest day the picker and the steps reach. */
6
+ min?: string;
7
+ max?: string;
8
+ /** Which days the steps land on (a trading calendar); every day when left out. */
9
+ isOpen?: (iso: string) => boolean;
10
+ /** What a day is called in the step tooltips: "Previous trading day". Default "day". */
11
+ unit?: string;
12
+ /** Shows a Today icon button that runs this. */
13
+ onToday?: () => void;
14
+ /** Today is already shown: the Today button is off. */
15
+ atToday?: boolean;
16
+ /** `sm` for toolbars and card headers, `default` in forms. */
17
+ size?: 'sm' | 'default';
18
+ disabled?: boolean;
19
+ id?: string;
20
+ 'aria-label'?: string;
21
+ className?: string;
22
+ };
23
+ /** The next open day from `iso` in direction `dir`, inside min and max; null when none. */
24
+ export declare function stepDate(iso: string, dir: 1 | -1, { min, max, isOpen }?: Pick<LumenDateInputProps, 'min' | 'max' | 'isOpen'>): string | null;
25
+ /**
26
+ * The kit's date picker: the browser's date input between ‹ and › icon buttons that step
27
+ * one open day (an app passes its trading calendar as `isOpen`), Alt+← and Alt+→ while it
28
+ * has focus, and an optional Today. Every date field in an app uses it.
29
+ */
30
+ export declare function LumenDateInput({ value, onChange, min, max, isOpen, unit, onToday, atToday, size, disabled, id, 'aria-label': ariaLabel, className, }: LumenDateInputProps): import("react").JSX.Element;
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // A date picker with ‹ › to step one open day back or forward, and an optional Today.
3
+ import { CalendarClockIcon, ChevronLeftIcon, ChevronRightIcon } from 'lucide-react';
4
+ import { IconButton } from './icon-button.js';
5
+ import { cn } from './lib/utils.js';
6
+ import { Input } from './ui/input.js';
7
+ const DAY = 86_400_000;
8
+ /** The furthest a step looks for an open day (long holiday runs fit easily). */
9
+ const REACH = 14;
10
+ function addDays(iso, n) {
11
+ return new Date(Date.parse(`${iso}T00:00:00Z`) + n * DAY).toISOString().slice(0, 10);
12
+ }
13
+ /** The next open day from `iso` in direction `dir`, inside min and max; null when none. */
14
+ export function stepDate(iso, dir, { min, max, isOpen } = {}) {
15
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(iso))
16
+ return null;
17
+ let day = iso;
18
+ for (let i = 0; i < REACH; i++) {
19
+ day = addDays(day, dir);
20
+ if ((min && day < min) || (max && day > max))
21
+ return null;
22
+ if (!isOpen || isOpen(day))
23
+ return day;
24
+ }
25
+ return null;
26
+ }
27
+ /**
28
+ * The kit's date picker: the browser's date input between ‹ and › icon buttons that step
29
+ * one open day (an app passes its trading calendar as `isOpen`), Alt+← and Alt+→ while it
30
+ * has focus, and an optional Today. Every date field in an app uses it.
31
+ */
32
+ export function LumenDateInput({ value, onChange, min, max, isOpen, unit = 'day', onToday, atToday, size = 'sm', disabled, id, 'aria-label': ariaLabel, className, }) {
33
+ const prev = disabled ? null : stepDate(value, -1, { min, max, isOpen });
34
+ const next = disabled ? null : stepDate(value, 1, { min, max, isOpen });
35
+ const btn = size === 'sm' ? 'icon-xs' : 'icon-sm';
36
+ const onKeyDown = (e) => {
37
+ if (!e.altKey)
38
+ return;
39
+ const to = e.key === 'ArrowLeft' ? prev : e.key === 'ArrowRight' ? next : undefined;
40
+ if (to === undefined)
41
+ return;
42
+ e.preventDefault();
43
+ if (to)
44
+ onChange(to);
45
+ };
46
+ return (_jsxs("div", { className: cn('inline-flex shrink-0 items-center gap-0.5', className), children: [_jsx(IconButton, { icon: ChevronLeftIcon, label: `Previous ${unit}`, size: btn, disabled: !prev, onClick: () => prev && onChange(prev) }), _jsx(Input, { type: "date", id: id, "aria-label": ariaLabel ?? 'Date', className: cn('tabular-nums', size === 'sm' ? 'h-7 w-32 text-xs md:text-xs' : 'w-36'), min: min, max: max, value: value, disabled: disabled, onKeyDown: onKeyDown, onChange: (e) => onChange(e.target.value) }), _jsx(IconButton, { icon: ChevronRightIcon, label: `Next ${unit}`, size: btn, disabled: !next, onClick: () => next && onChange(next) }), onToday && (_jsx(IconButton, { icon: CalendarClockIcon, label: "Today", size: btn, disabled: disabled || atToday, onClick: onToday }))] }));
47
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@columenlabs/lumen-ui",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -41,7 +41,7 @@
41
41
  "@codemirror/lang-javascript": "6.2.5",
42
42
  "@codemirror/lang-json": "6.0.2",
43
43
  "@codemirror/lang-sql": "6.10.0",
44
- "@columenlabs/lumen-ui-types": "0.1.17",
44
+ "@columenlabs/lumen-ui-types": "0.1.18",
45
45
  "@dnd-kit/core": "6.3.1",
46
46
  "@dnd-kit/sortable": "10.0.0",
47
47
  "@dnd-kit/utilities": "3.2.2",